Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FEAT(stark252 field): Adds Stark252 curve #494

Merged
merged 9 commits into from
May 1, 2024
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,10 @@ jobs:
if: needs.check-changed-files.outputs.rust == 'true' || needs.check-changed-files.outputs.cpp_cuda == 'true'
# Running tests from the root workspace will run all workspace members' tests by default
# We need to limit the number of threads to avoid running out of memory on weaker machines
# ignored tests are polynomial tests. Since they conflict with NTT tests, they are executed sperately
# ignored tests are polynomial tests. Since they conflict with NTT tests, they are executed separately
run: |
cargo test --workspace --exclude icicle-babybear --release --verbose --features=g2 -- --test-threads=2 --ignored
cargo test --workspace --exclude icicle-babybear --release --verbose --features=g2 -- --test-threads=2
cargo test --workspace --exclude icicle-babybear icicle-stark252 --release --verbose --features=g2 -- --test-threads=2 --ignored
jeremyfelder marked this conversation as resolved.
Show resolved Hide resolved
cargo test --workspace --exclude icicle-babybear icicle-stark252 --release --verbose --features=g2 -- --test-threads=2

- name: Run baby bear tests
working-directory: ./wrappers/rust/icicle-fields/icicle-babybear
Expand All @@ -72,6 +72,13 @@ jobs:
cargo test --release --verbose -- --ignored
cargo test --release --verbose

- name: Run stark252 tests
working-directory: ./wrappers/rust/icicle-fields/icicle-stark252
if: needs.check-changed-files.outputs.rust == 'true' || needs.check-changed-files.outputs.cpp_cuda == 'true'
run: |
cargo test --release --verbose -- --ignored
cargo test --release --verbose

build-windows:
name: Build on Windows
runs-on: windows-2022
Expand Down
4 changes: 2 additions & 2 deletions icicle/cmake/FieldsCommon.cmake
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
function(check_field)
set(SUPPORTED_FIELDS babybear)
set(SUPPORTED_FIELDS babybear;stark252)

set(IS_FIELD_SUPPORTED FALSE)
set(I 1000)
Expand All @@ -14,4 +14,4 @@ function(check_field)
if (NOT IS_FIELD_SUPPORTED)
message( FATAL_ERROR "The value of FIELD variable: ${FIELD} is not one of the supported fields: ${SUPPORTED_FIELDS}" )
endif ()
endfunction()
endfunction()
47 changes: 47 additions & 0 deletions icicle/include/api/stark252.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// WARNING: This file is auto-generated by a script.
// Any changes made to this file may be overwritten.
// Please modify the code generation script instead.
// Path to the code generation script: scripts/gen_c_api.py

#pragma once
#ifndef STARK252_API_H
#define STARK252_API_H

#include <cuda_runtime.h>
#include "gpu-utils/device_context.cuh"
#include "fields/stark_fields/stark252.cuh"
#include "ntt/ntt.cuh"
#include "vec_ops/vec_ops.cuh"

extern "C" cudaError_t stark252_mul_cuda(
stark252::scalar_t* vec_a, stark252::scalar_t* vec_b, int n, vec_ops::VecOpsConfig& config, stark252::scalar_t* result);

extern "C" cudaError_t stark252_add_cuda(
stark252::scalar_t* vec_a, stark252::scalar_t* vec_b, int n, vec_ops::VecOpsConfig& config, stark252::scalar_t* result);

extern "C" cudaError_t stark252_sub_cuda(
stark252::scalar_t* vec_a, stark252::scalar_t* vec_b, int n, vec_ops::VecOpsConfig& config, stark252::scalar_t* result);

extern "C" cudaError_t stark252_transpose_matrix_cuda(
const stark252::scalar_t* input,
uint32_t row_size,
uint32_t column_size,
stark252::scalar_t* output,
device_context::DeviceContext& ctx,
bool on_device,
bool is_async);

extern "C" void stark252_generate_scalars(stark252::scalar_t* scalars, int size);

extern "C" cudaError_t stark252_scalar_convert_montgomery(
stark252::scalar_t* d_inout, size_t n, bool is_into, device_context::DeviceContext& ctx);

extern "C" cudaError_t stark252_initialize_domain(
stark252::scalar_t* primitive_root, device_context::DeviceContext& ctx, bool fast_twiddles_mode);

extern "C" cudaError_t stark252_ntt_cuda(
const stark252::scalar_t* input, int size, ntt::NTTDir dir, ntt::NTTConfig<stark252::scalar_t>& config, stark252::scalar_t* output);

extern "C" cudaError_t stark252_release_domain(device_context::DeviceContext& ctx);

#endif
3 changes: 3 additions & 0 deletions icicle/include/fields/field_config.cuh
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ namespace field_config = grumpkin;
#elif FIELD_ID == BABY_BEAR
#include "fields/stark_fields/babybear.cuh"
namespace field_config = babybear;
#elif FIELD_ID == STARK_252
#include "fields/stark_fields/stark252.cuh"
namespace field_config = stark252;
#endif

#endif
1 change: 1 addition & 0 deletions icicle/include/fields/id.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@
#define GRUMPKIN 5

#define BABY_BEAR 1001
#define STARK_252 1002

#endif
631 changes: 631 additions & 0 deletions icicle/include/fields/stark_fields/stark252.cuh

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions scripts/gen_c_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@
FIELDS_CONFIG = {
"babybear": {
"poseidon.h",
},
"stark252": {
"poseidon.h",
"field_ext.h",
ChickenLover marked this conversation as resolved.
Show resolved Hide resolved
"vec_ops_ext.h",
"ntt_ext.h",
}
}

Expand Down
1 change: 1 addition & 0 deletions wrappers/rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ members = [
"icicle-curves/icicle-bn254",
"icicle-curves/icicle-grumpkin",
"icicle-fields/icicle-babybear",
"icicle-fields/icicle-stark252",
"icicle-hash",
]
exclude = [
Expand Down
22 changes: 22 additions & 0 deletions wrappers/rust/icicle-fields/icicle-stark252/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[package]
name = "icicle-stark252"
version.workspace = true
edition.workspace = true
authors.workspace = true
description = "Rust wrapper for the CUDA implementation of stark252 prime field by Ingonyama"
homepage.workspace = true
repository.workspace = true

[dependencies]
icicle-core = { workspace = true }
icicle-cuda-runtime = { workspace = true }

[build-dependencies]
cmake = "0.1.50"

[dev-dependencies]
lambdaworks-math = "0.6.0"

[features]
default = []
devmode = ["icicle-core/devmode"]
24 changes: 24 additions & 0 deletions wrappers/rust/icicle-fields/icicle-stark252/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use cmake::Config;

fn main() {
println!("cargo:rerun-if-env-changed=CXXFLAGS");
println!("cargo:rerun-if-changed=../../../../icicle");

// Base config
let mut config = Config::new("../../../../icicle/");
config
.define("FIELD", "stark252")
.define("CMAKE_BUILD_TYPE", "Release")
.define("EXT_FIELD", "OFF");

// Build
let out_dir = config
.build_target("icicle_field")
.build();

println!("cargo:rustc-link-search={}/build/lib", out_dir.display());

println!("cargo:rustc-link-lib=ingo_field_stark252");
println!("cargo:rustc-link-lib=stdc++");
println!("cargo:rustc-link-lib=cudart");
}
19 changes: 19 additions & 0 deletions wrappers/rust/icicle-fields/icicle-stark252/src/field.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use icicle_core::field::{Field, MontgomeryConvertibleField};
use icicle_core::traits::{FieldConfig, FieldImpl, GenerateRandom};
use icicle_core::{impl_field, impl_scalar_field};
use icicle_cuda_runtime::device::check_device;
use icicle_cuda_runtime::device_context::DeviceContext;
use icicle_cuda_runtime::error::CudaError;
use icicle_cuda_runtime::memory::{DeviceSlice, HostOrDeviceSlice};

pub(crate) const SCALAR_LIMBS: usize = 8;

impl_scalar_field!("stark252", stark252, SCALAR_LIMBS, ScalarField, ScalarCfg, Fr);
#[cfg(test)]
mod tests {
use super::ScalarField;
use icicle_core::impl_field_tests;
use icicle_core::tests::*;

impl_field_tests!(ScalarField);
}
4 changes: 4 additions & 0 deletions wrappers/rust/icicle-fields/icicle-stark252/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
pub mod field;
pub mod ntt;
pub mod polynomials;
pub mod vec_ops;
60 changes: 60 additions & 0 deletions wrappers/rust/icicle-fields/icicle-stark252/src/ntt/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
use crate::field::{ScalarCfg, ScalarField};

use icicle_core::error::IcicleResult;
use icicle_core::ntt::{NTTConfig, NTTDir, NTTDomain, NTT};
use icicle_core::traits::IcicleResultWrap;
use icicle_core::{impl_ntt, impl_ntt_without_domain};
use icicle_cuda_runtime::device_context::DeviceContext;
use icicle_cuda_runtime::error::CudaError;
use icicle_cuda_runtime::memory::HostOrDeviceSlice;

impl_ntt!("stark252", stark252, ScalarField, ScalarCfg);

#[cfg(test)]
pub(crate) mod tests {
use super::ScalarField;
use icicle_core::{
ntt::{initialize_domain, ntt_inplace, NTTConfig, NTTDir},
traits::{FieldImpl, GenerateRandom},
};
use icicle_cuda_runtime::{device_context::DeviceContext, memory::HostSlice};
use lambdaworks_math::{
field::{
element::FieldElement, fields::fft_friendly::stark_252_prime_field::Stark252PrimeField, traits::IsFFTField,
},
polynomial::Polynomial,
traits::ByteConversion,
};

pub type FE = FieldElement<Stark252PrimeField>;

#[test]
fn test_against_lambdaworks() {
let log_sizes = [15, 20];
let ctx = DeviceContext::default();
let lw_root_of_unity = Stark252PrimeField::get_primitive_root_of_unity(log_sizes[log_sizes.len() - 1]).unwrap();
initialize_domain(ScalarField::from_bytes_le(&lw_root_of_unity.to_bytes_le()), &ctx, false).unwrap();
for log_size in log_sizes {
let ntt_size = 1 << log_size;

let mut scalars: Vec<ScalarField> = <ScalarField as FieldImpl>::Config::generate_random(ntt_size);
let scalars_lw: Vec<FE> = scalars
.iter()
.map(|x| FieldElement::from_bytes_le(&x.to_bytes_le()).unwrap())
.collect();

let ntt_cfg: NTTConfig<'_, ScalarField> = NTTConfig::default();
ntt_inplace(HostSlice::from_mut_slice(&mut scalars[..]), NTTDir::kForward, &ntt_cfg).unwrap();

let poly = Polynomial::new(&scalars_lw[..]);
let evaluations = Polynomial::evaluate_fft::<Stark252PrimeField>(&poly, 1, None).unwrap();

for (s1, s2) in scalars
.iter()
.zip(evaluations.iter())
{
assert_eq!(s1.to_bytes_le(), s2.to_bytes_le());
}
}
}
}
10 changes: 10 additions & 0 deletions wrappers/rust/icicle-fields/icicle-stark252/src/polynomials/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
use crate::field::{ScalarCfg, ScalarField};
use icicle_core::impl_univariate_polynomial_api;

impl_univariate_polynomial_api!("stark252", stark252, ScalarField, ScalarCfg);

#[cfg(test)]
mod tests {
use icicle_core::impl_polynomial_tests;
impl_polynomial_tests!(stark252, ScalarField);
}
20 changes: 20 additions & 0 deletions wrappers/rust/icicle-fields/icicle-stark252/src/vec_ops/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use crate::field::{ScalarCfg, ScalarField};

use icicle_core::error::IcicleResult;
use icicle_core::impl_vec_ops_field;
use icicle_core::traits::IcicleResultWrap;
use icicle_core::vec_ops::{VecOps, VecOpsConfig};
use icicle_cuda_runtime::device_context::DeviceContext;
use icicle_cuda_runtime::error::CudaError;
use icicle_cuda_runtime::memory::HostOrDeviceSlice;

impl_vec_ops_field!("stark252", stark252, ScalarField, ScalarCfg);

#[cfg(test)]
pub(crate) mod tests {
use crate::field::ScalarField;
use icicle_core::impl_vec_add_tests;
use icicle_core::vec_ops::tests::*;

impl_vec_add_tests!(ScalarField);
}
Loading