### Build and Run ICICLE PQC Example Source: https://github.com/ingonyama-zk/icicle/blob/main/examples/c++/pqc-package/README.md Use the run script to build and execute the ICICLE PQC example, optionally specifying an installation path and batch size. ```bash ./run.sh /path/to/icicle/pqc/install ./run.sh /path/to/icicle/pqc/install 10 export ICICLE_PQC_INSTALL_DIR=/path/to/icicle/pqc/install ./run.sh ./run.sh --help ``` -------------------------------- ### Running ICICLE Example Scripts Source: https://github.com/ingonyama-zk/icicle/blob/main/examples/c++/best-practice-ntt/README.md These commands demonstrate how to execute the ICICLE example scripts for different compute devices (CPU, CUDA, METAL). Ensure the backend installation directory is correctly specified for CUDA and METAL. ```shell # for CPU ./run.sh -d CPU # for CUDA ./run.sh -d CUDA -b /path/to/cuda/backend/install/dir # for METAL ./run.sh -d METAL -b /path/to/cuda/backend/install/dir ``` -------------------------------- ### Run Sumcheck Example Source: https://github.com/ingonyama-zk/icicle/blob/main/examples/rust/sumcheck/README.md Execute the sumcheck example script. Specify the device (CPU/CUDA) and optionally the CUDA backend installation directory. ```sh # for CPU ./run.sh -d CPU # for CUDA ./run.sh -d CUDA -b /path/to/cuda/backend/install/dir # for METAL (not supported yet) ./run.sh -d METAL -b /path/to/cuda/backend/install/dir ``` -------------------------------- ### Load CUDA Backend and Select Device in Go Source: https://github.com/ingonyama-zk/icicle/blob/main/README.md Load the CUDA backend using environment defaults or a custom installation directory. After loading, create and set a CUDA device for computations. This setup ensures all subsequent calls utilize the specified GPU. ```go import( "github.com/ingonyama-zk/icicle/v3/wrappers/golang/runtime" ) result := runtime.LoadBackendFromEnvOrDefault() // or load from custom install dir result := runtime.LoadBackend("/path/to/backend/installdir", true) // Select CUDA device device := runtime.CreateDevice("CUDA", 0) // or other result := runtime.SetDevice(device) // Any call will now execute on GPU-0 ``` -------------------------------- ### Example of Creating Version 5.6.0 Source: https://github.com/ingonyama-zk/icicle/blob/main/docs/README.md This is an example of how to use the `docs:version` command to create documentation for version 5.6.0. ```sh npm run docusaurus docs:version 5.6.0 ``` -------------------------------- ### Run ICICLE Example on METAL Source: https://github.com/ingonyama-zk/icicle/blob/main/examples/rust/polynomials/README.md Execute the ICICLE example using the METAL backend. Provide the installation directory for the CUDA backend. ```sh ./run.sh -d METAL -b /path/to/cuda/backend/install/dir ``` -------------------------------- ### Run ICICLE Example with CPU or CUDA Backend Source: https://github.com/ingonyama-zk/icicle/blob/main/examples/rust/arkworks-icicle-conversions/README.md Execute the ICICLE example using either the CPU or CUDA backend. For CUDA, specify the backend installation directory. ```sh # For CPU ./run.sh -d CPU # For CUDA ./run.sh -d CUDA -b /path/to/cuda/backend/install/dir ``` -------------------------------- ### Run ICICLE Example on CUDA Source: https://github.com/ingonyama-zk/icicle/blob/main/examples/rust/polynomials/README.md Execute the ICICLE example using the CUDA backend. Provide the installation directory for the CUDA backend. ```sh ./run.sh -d CUDA -b /path/to/cuda/backend/install/dir ``` -------------------------------- ### Run ICICLE Polynomial Example Source: https://github.com/ingonyama-zk/icicle/blob/main/examples/golang/polynomials/README.md Execute the Golang example using the command `go run main.go`. This will demonstrate polynomial arithmetic and evaluations. ```sh go run main.go ``` -------------------------------- ### Multi GPU Example Source: https://github.com/ingonyama-zk/icicle/blob/main/docs/versioned_docs/version-4.0.0/api/golang-bindings/multi-gpu.md This example demonstrates how to fetch the number of available GPUs, launch a thread for each GPU, set an active device per thread, and execute an MSM on each GPU. ```APIDOC ## Multi GPU Example This example demonstrates a basic pattern for distributing tasks across multiple GPUs. The `RunOnDevice` function ensures that each goroutine is executed on its designated GPU and a corresponding thread. ```go package main import ( "fmt" "sync" "github.com/ingonyama-zk/icicle/v3/wrappers/golang/core" bn254 "github.com/ingonyama-zk/icicle/v3/wrappers/golang/curves/bn254" "github.com/ingonyama-zk/icicle/v3/wrappers/golang/curves/bn254/msm" "github.com/ingonyama-zk/icicle/v3/wrappers/golang/runtime" ) func main() { // Load backend using env path runtime.LoadBackendFromEnvOrDefault() device := runtime.CreateDevice("CUDA", 0) err := runtime.SetDevice(&device) numDevices, _ := runtime.GetDeviceCount() fmt.Println("There are ", numDevices, " devices available") if err != runtime.Success { panic(err) } wg := sync.WaitGroup{} for i := 0; i < numDevices; i++ { internalDevice := runtime.Device{DeviceType: device.DeviceType, Id: int32(i)} wg.Add(1) runtime.RunOnDevice(&internalDevice, func(args ...any) { defer wg.Done() currentDevice, err := runtime.GetActiveDevice() if err != runtime.Success { panic("Failed to get current device") } fmt.Println("Running on ", currentDevice.GetDeviceType(), " ", currentDevice.Id, " device") cfg := msm.GetDefaultMSMConfig() cfg.IsAsync = true size := 1 << 10 scalars := bn254.GenerateScalars(size) points := bn254.GenerateAffinePoints(size) stream, _ := runtime.CreateStream() var p bn254.Projective var out core.DeviceSlice _, err = out.MallocAsync(p.Size(), 1, stream) if err != runtime.Success { panic("Allocating bytes on device for Projective results failed") } cfg.StreamHandle = stream err = msm.Msm(scalars, points, &cfg, out) if err != runtime.Success { panic("Msm failed") } outHost := make(core.HostSlice[bn254.Projective], 1) outHost.CopyFromDeviceAsync(&out, stream) out.FreeAsync(stream) runtime.SynchronizeStream(stream) runtime.DestroyStream(stream) // Check with gnark-crypto }) } wg.Wait() } ``` ``` -------------------------------- ### Run ICICLE Example with RISC0 Source: https://github.com/ingonyama-zk/icicle/blob/main/examples/c++/risc0/README.md Execute the ICICLE example for RISC0's Fibonacci sequence proof. Specify the backend (CPU, CUDA, or METAL) for execution. For CUDA and METAL, provide the installation directory of the backend. ```sh ./run.sh -d CPU ``` ```sh ./run.sh -d CUDA -b /path/to/cuda/backend/install/dir ``` ```sh ./run.sh -d METAL -b /path/to/cuda/backend/install/dir ``` -------------------------------- ### Install ICICLE Frontend Libraries and CUDA Backend Source: https://context7.com/ingonyama-zk/icicle/llms.txt Extract and install frontend libraries to system paths. Optionally, install the CUDA backend to a specified directory. ```bash # Extract and install frontend libraries tar xzvf icicle30-ubuntu22.tar.gz cp -r ./icicle/lib/* /usr/lib/ cp -r ./icicle/include/icicle/ /usr/local/include/ # Install CUDA backend (optional) tar xzvf icicle30-ubuntu22-cuda122.tar.gz -C /opt ``` -------------------------------- ### Install CUDA PQC Backend Targets Source: https://github.com/ingonyama-zk/icicle/blob/main/icicle/backend/cuda_pqc/CMakeLists.txt Installs the built CUDA PQC backend library and its interface library to the specified installation prefix. This makes the library available for use by other projects after the build system has finished. The installation destinations are configured for runtime, library, and archive files. ```cmake # Install targets install(TARGETS icicle_backend_cuda_pqc icicle_backend_cuda_pqc_interface RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/" LIBRARY DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/" ARCHIVE DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/") ``` -------------------------------- ### Build ICICLE PQC Example Source: https://github.com/ingonyama-zk/icicle/blob/main/examples/c++/pqc-package/README.md Use the build script to compile the ICICLE PQC example without running it. ```bash ./build.sh ``` -------------------------------- ### Run ICICLE Example on CPU Source: https://github.com/ingonyama-zk/icicle/blob/main/examples/rust/polynomials/README.md Execute the ICICLE example using the CPU backend. Ensure the script is executable. ```sh ./run.sh -d CPU ``` -------------------------------- ### Run Golang NTT Example Source: https://github.com/ingonyama-zk/icicle/blob/main/examples/golang/ntt/README.md Execute the main Golang NTT example. The default NTT size is 2^20, but can be changed using the -s flag. ```sh go run main.go ``` ```sh go run main.go -s=23 ``` -------------------------------- ### Polynomial Operations Example Source: https://github.com/ingonyama-zk/icicle/blob/main/docs/versioned_docs/version-4.0.0/start/programmers_guide/go.md Demonstrates polynomial operations, specifically multiplication, using Icicle's APIs over the babybear field. It includes setup for NTT domains and polynomial creation. ```go package main import ( "fmt" "github.com/ingonyama-zk/icicle/v3/wrappers/golang/core" "github.com/ingonyama-zk/icicle/v3/wrappers/golang/runtime" "github.com/ingonyama-zk/icicle/v3/wrappers/golang/fields/babybear" "github.com/ingonyama-zk/icicle/v3/wrappers/golang/fields/babybear/ntt" "github.com/ingonyama-zk/icicle/v3/wrappers/golang/fields/babybear/polynomial" ) func initBabybearDomain() runtime.EIcicleError { cfgInitDomain := core.GetDefaultNTTInitDomainConfig() rouIcicle := babybear.ScalarField{} rouIcicle.FromUint32(1461624142) return ntt.InitDomain(rouIcicle, cfgInitDomain) } func init() { // Load installed backends runtime.LoadBackendFromEnvOrDefault() // trying to choose CUDA if available, or fallback to CPU otherwise (default device) deviceCuda := runtime.CreateDevice("CUDA", 0) // GPU-0 if runtime.IsDeviceAvailable(&deviceCuda) { runtime.SetDevice(&deviceCuda) } // else we stay on CPU backend // build domain for ntt is required for some polynomial ops that rely on ntt err := initBabybearDomain() if err != runtime.Success { errorString := fmt.Sprint( "Babybear Domain initialization failed: ", err) panic(errorString) } } func main() { // Setup inputs const polySize = 1 << 10 // randomize two polynomials over babybear field var fBabybear polynomial.DensePolynomial defer fBabybear.Delete() var gBabybear polynomial.DensePolynomial defer gBabybear.Delete() fBabybear.CreateFromCoeffecitients(babybear.GenerateScalars(polySize)) gBabybear.CreateFromCoeffecitients(babybear.GenerateScalars(polySize / 2)) // Perform polynomial multiplication rBabybear := fBabybear.Multiply(&gBabybear) // Executes on the current device defer rBabybear.Delete() rDegree := rBabybear.Degree() fmt.Println("f Degree: ", fBabybear.Degree()) fmt.Println("g Degree: ", gBabybear.Degree()) fmt.Println("r Degree: ", rDegree) } ``` -------------------------------- ### Run ICICLE MSM Example Source: https://github.com/ingonyama-zk/icicle/blob/main/examples/golang/msm/README.md Execute the main Go program to run the MSM example. Default sizes range from 2^17 to 2^22. Use command-line flags to adjust the size range. ```sh go run main.go ``` ```sh go run main.go -l=21 -u=24 ``` -------------------------------- ### Sumcheck Example Output (Ubuntu Desktop with GPU) Source: https://github.com/ingonyama-zk/icicle/blob/main/examples/rust/sumcheck/README.md Sample output logs from running the sumcheck example on Ubuntu Desktop with an RTX 4080 GPU, including license server information and performance metrics. ```rust [WARNING] Defaulting to Ingonyama icicle-cuda-license-server at `5053@license.icicle.ingonyama.com`. For more information about icicle-cuda-license, please contact support@ingonyama.com. [2025-02-17T21:10:33Z INFO sumcheck] Generate e,A,B,C of log size 22, time 890.615763ms [2025-02-17T21:10:33Z INFO sumcheck] Compute claimed sum time 374.166708ms [2025-02-17T21:10:34Z INFO sumcheck] Prover time 224.319171ms Valid proof! [2025-02-17T21:10:34Z INFO sumcheck] verify time 183.244µs [2025-02-17T21:10:34Z INFO sumcheck] total time 1.489436224s ``` -------------------------------- ### Build and Install ICICLE PQC Source: https://github.com/ingonyama-zk/icicle/blob/main/examples/c++/pqc-package/README.md Build the ICICLE PQC library from source using CMake and then install it to the specified prefix. ```bash cmake --build build -j cmake --install build ``` -------------------------------- ### ECNTT Example Source: https://github.com/ingonyama-zk/icicle/blob/main/docs/versioned_docs/version-4.0.0/api/golang-bindings/ecntt.md Example demonstrating how to use the ECNtt function. ```APIDOC ## ECNTT Example ### Description This example demonstrates the basic usage of the `ECNtt` function, including setting up the runtime, configuring the NTT, generating points, and performing the transform. ### Code Example ```go package main import ( "github.com/ingonyama-zk/icicle/v3/wrappers/golang/core" "github.com/ingonyama-zk/icicle/v3/wrappers/golang/curves/bn254" "github.com/ingonyama-zk/icicle/v3/wrappers/golang/curves/bn254/ecntt" "github.com/ingonyama-zk/icicle/v3/wrappers/golang/curves/bn254/ntt" "github.com/ingonyama-zk/icicle/v3/wrappers/golang/runtime" ) func Main() { // Load backend using env path runtime.LoadBackendFromEnvOrDefault() // Set Cuda device to perform device := runtime.CreateDevice("CUDA", 0) runtime.SetDevice(&device) // Obtain the default NTT configuration with a predefined coset generator. cfg := ntt.GetDefaultNttConfig() // Define the size of the input scalars. size := 1 << 18 // Generate Points for the ECNTT operation. points := bn254.GenerateProjectivePoints(size) // Set the direction of the NTT (forward or inverse). dir := core.KForward // Allocate memory for the results of the NTT operation. res := make(core.HostSlice[bn254.Projective], size) // Perform the NTT operation. err := ecntt.ECNtt(points, dir, &cfg, results) if err != runtime.Success { panic("ECNTT operation failed") } } ``` ``` -------------------------------- ### Start Local Development Server Source: https://github.com/ingonyama-zk/icicle/blob/main/docs/README.md Run this command to start a local development server for rendering the Docusaurus site. Changes are typically reflected live. ```sh npm start ``` -------------------------------- ### Install ICICLE with CMake (C++) Source: https://github.com/ingonyama-zk/icicle/blob/main/README.md Configure CMake to specify an installation directory and then build and install the ICICLE libraries. ```bash cmake -S icicle -B build -DFIELD=babybear -DCMAKE_INSTALL_PREFIX=/path/to/install/dir/ cmake --build build -j # build cmake --install build # install icicle to /path/to/install/dir/ ``` -------------------------------- ### Configure ICICLE PQC Example Build Source: https://github.com/ingonyama-zk/icicle/blob/main/examples/c++/pqc-package/CMakeLists.txt This CMake script sets up the build environment for an example project using ICICLE PQC. Ensure the ICICLE_PQC_INSTALL_DIR is provided during the CMake configuration step. ```cmake cmake_minimum_required(VERSION 3.18) project(icicle_pqc_example) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) # ICICLE PQC installation directory set(ICICLE_PQC_INSTALL_DIR "" CACHE PATH "Path to ICICLE PQC installation directory") if(NOT ICICLE_PQC_INSTALL_DIR) message(FATAL_ERROR "Please specify: cmake .. -DICICLE_PQC_INSTALL_DIR=/path/to/icicle/install") endif() # Find ICICLE package find_package(icicle_pqc_package REQUIRED PATHS ${ICICLE_PQC_INSTALL_DIR}) # Create executable add_executable(pqc_example pqc_example.cpp) # Link ICICLE PQC package target_link_libraries(pqc_example PRIVATE icicle::icicle_pqc_package) get_target_property(interface_includes icicle::icicle_pqc_package INTERFACE_INCLUDE_DIRECTORIES) message(STATUS "Interface includes for icicle::icicle_pqc_package: ${interface_includes}") ``` -------------------------------- ### Sumcheck Example Output (M1 Mac) Source: https://github.com/ingonyama-zk/icicle/blob/main/examples/rust/sumcheck/README.md Sample output logs from running the sumcheck example on an M1 Mac, showing generation times, computation times, and verification results. ```rust [2025-02-17T20:57:25Z INFO sumcheck] Generate e,A,B,C of log size 22, time 954.447375ms [2025-02-17T20:57:26Z INFO sumcheck] Compute claimed sum time 439.200917ms [2025-02-17T20:57:28Z INFO sumcheck] Prover time 2.383280625s Valid proof! [2025-02-17T20:57:28Z INFO sumcheck] verify time 201.666µs [2025-02-17T20:57:28Z INFO sumcheck] total time 3.777288875s ``` -------------------------------- ### Run ICICLE PQC Example Manually Source: https://github.com/ingonyama-zk/icicle/blob/main/examples/c++/pqc-package/README.md Execute the compiled ICICLE PQC example directly, specifying a batch size if needed. ```bash ./build/pqc_example ./build/pqc_example 10 ./build/pqc_example 100 ``` -------------------------------- ### Compile C++ Example with CMake Source: https://github.com/ingonyama-zk/icicle/blob/main/examples/c++/install-and-use-icicle/README.md Configures and builds a C++ example project using CMake. Assumes the project source is in the current directory and build artifacts will be placed in a 'build' subdirectory. ```bash cd .. mkdir build cmake -S . -B build && cmake --build build ``` -------------------------------- ### Extract and Install ICICLE Frontend Source: https://github.com/ingonyama-zk/icicle/blob/main/examples/c++/install-and-use-icicle/README.md Extracts the ICICLE frontend binaries from a tarball and installs the library files and C++ headers to system-wide locations (/usr/lib and /usr/local/include). ```bash cd release # extract frontend part tar xzvf icicle30-ubuntu22.tar.gz cp -r ./icicle/lib/* /usr/lib/ cp -r ./icicle/include/icicle/ /usr/local/include/ # copy C++ headers ``` -------------------------------- ### Install ICICLE to Custom Location Source: https://github.com/ingonyama-zk/icicle/blob/main/examples/c++/install-and-use-icicle/README.md Installs ICICLE frontend and optional CUDA backend binaries to a specified custom path (e.g., /custom/path). Creates the directory if it doesn't exist. ```bash mkdir -p /custom/path cd release tar xzvf icicle30-ubuntu22.tar.gz -C /custom/path tar xzvf icicle30-ubuntu22-cuda122.tar.gz -C /custom/path # OPTIONAL ``` -------------------------------- ### ECNTT Example in Go Source: https://github.com/ingonyama-zk/icicle/blob/main/docs/versioned_docs/version-4.0.0/api/golang-bindings/ecntt.md Demonstrates initializing the backend, setting the device, obtaining default NTT configuration, generating points, and performing an ECNTT operation. Handles potential errors during the operation. ```go package main import ( "github.com/ingonyama-zk/icicle/v3/wrappers/golang/core" "github.com/ingonyama-zk/icicle/v3/wrappers/golang/curves/bn254" "github.com/ingonyama-zk/icicle/v3/wrappers/golang/curves/bn254/ecntt" "github.com/ingonyama-zk/icicle/v3/wrappers/golang/curves/bn254/ntt" "github.com/ingonyama-zk/icicle/v3/wrappers/golang/runtime" ) func Main() { // Load backend using env path runtime.LoadBackendFromEnvOrDefault() // Set Cuda device to perform device := runtime.CreateDevice("CUDA", 0) runtime.SetDevice(&device) // Obtain the default NTT configuration with a predefined coset generator. cfg := ntt.GetDefaultNttConfig() // Define the size of the input scalars. size := 1 << 18 // Generate Points for the ECNTT operation. points := bn254.GenerateProjectivePoints(size) // Set the direction of the NTT (forward or inverse). dir := core.KForward // Allocate memory for the results of the NTT operation. results := make(core.HostSlice[bn254.Projective], size) // Perform the NTT operation. err := ecntt.ECNtt(points, dir, &cfg, results) if err != runtime.Success { panic("ECNTT operation failed") } } ``` -------------------------------- ### Example: Computing NTT with Default Config Source: https://github.com/ingonyama-zk/icicle/blob/main/docs/versioned_docs/version-4.0.0/api/rust-bindings/ntt.md Demonstrates setting up scalar fields, allocating device memory, initializing the NTT domain, and computing the forward NTT using default configuration. ```rust // Setting Bn254 points and scalars println!("Generating random inputs on host for bn254..."); let scalars = ScalarField::generate_random(size); let mut ntt_results = DeviceVec::::device_malloc(size).unwrap(); // constructing NTT domain initialize_domain( ntt::get_root_of_unity::( size.try_into().unwrap(), ), &ntt::NTTInitDomainConfig::default(), ) .unwrap(); // Using default config let cfg = ntt::NTTConfig::::default(); // Computing NTT ntt::ntt( HostSlice::from_slice(&scalars), ntt::NTTDir::kForward, &cfg, &mut ntt_results[..], ) .unwrap(); ``` -------------------------------- ### Initialize and Run NTT in Go Source: https://github.com/ingonyama-zk/icicle/blob/main/docs/versioned_docs/version-4.0.0/api/golang-bindings/ntt.md Demonstrates initializing the NTT domain, generating scalars, performing a forward NTT, and releasing the domain. Ensure the backend is loaded and a CUDA device is set. ```go package main import ( "github.com/ingonyama-zk/icicle/v3/wrappers/golang/core" "github.com/ingonyama-zk/icicle/v3/wrappers/golang/curves/bn254" "github.com/ingonyama-zk/icicle/v3/wrappers/golang/curves/bn254/ntt" "github.com/ingonyama-zk/icicle/v3/wrappers/golang/runtime" "github.com/consensys/gnark-crypto/ecc/bn254/fr/fft" ) func init() { // Load backend using env path runtime.LoadBackendFromEnvOrDefault() // Set Cuda device to perform device := runtime.CreateDevice("CUDA", 0) runtime.SetDevice(&device) cfg := core.GetDefaultNTTInitDomainConfig() initDomain(18, cfg) } func initDomain(largestTestSize int, cfg core.NTTInitDomainConfig) runtime.EIcicleError { rouMont, _ := fft.Generator(uint64(1 << largestTestSize)) rou := rouMont.Bits() rouIcicle := bn254.ScalarField{} limbs := core.ConvertUint64ArrToUint32Arr(rou[:]) rouIcicle.FromLimbs(limbs) e := ntt.InitDomain(rouIcicle, cfg) return e } func main() { // Obtain the default NTT configuration with a predefined coset generator. cfg := ntt.GetDefaultNttConfig() // Define the size of the input scalars. size := 1 << 18 // Generate scalars for the NTT operation. scalars := bn254.GenerateScalars(size) // Set the direction of the NTT (forward or inverse). dir := core.KForward // Allocate memory for the results of the NTT operation. results := make(core.HostSlice[bn254.ScalarField], size) // Perform the NTT operation. err := ntt.Ntt(scalars, dir, &cfg, results) if err != runtime.Success { panic("NTT operation failed") } ntt.ReleaseDomain() } ``` -------------------------------- ### Quick-start Example: ML-KEM Host Buffer Operations Source: https://github.com/ingonyama-zk/icicle/blob/main/docs/versioned_docs/version-4.0.0/api/rust-bindings/lattice/pqc-ml-kem.md Demonstrates a full ML-KEM cycle (keygen, encapsulate, decapsulate) using host buffers with Kyber768 parameters. It initializes buffers, sets up configuration, performs operations, and asserts the correctness of the shared secrets. Ensure `is_async = true` is handled by synchronizing the stream before reading results. ```rust use icicle_ml_kem as mlkem; use icicle_ml_kem::{keygen, encapsulate, decapsulate}; use icicle_ml_kem::kyber_params::{Kyber768Params, ENTROPY_BYTES, MESSAGE_BYTES}; use icicle_runtime::memory::HostSlice; use rand::{RngCore, rngs::OsRng}; const BATCH: usize = 1 << 12; fn main() { // Allocate buffers on the host let mut entropy = vec![0u8; BATCH * ENTROPY_BYTES]; let mut msg = vec![0u8; BATCH * MESSAGE_BYTES]; OsRng.fill_bytes(&mut entropy); OsRng.fill_bytes(&mut msg); let mut pk = vec![0u8; BATCH * Kyber768Params::PUBLIC_KEY_BYTES]; let mut sk = vec![0u8; BATCH * Kyber768Params::SECRET_KEY_BYTES]; let mut ct = vec![0u8; BATCH * Kyber768Params::CIPHERTEXT_BYTES]; let mut ss_enc = vec![0u8; BATCH * Kyber768Params::SHARED_SECRET_BYTES]; let mut ss_dec = vec![0u8; BATCH * Kyber768Params::SHARED_SECRET_BYTES]; // Configuration – everything stays on host let mut cfg = mlkem::config::MlKemConfig::default(); cfg.batch_size = BATCH as i32; // Key generation keygen::( HostSlice::from_slice(&entropy), &cfg, HostSlice::from_mut_slice(&mut pk), HostSlice::from_mut_slice(&mut sk), ).unwrap(); // Encapsulation encapsulate::( HostSlice::from_slice(&msg), HostSlice::from_slice(&pk), &cfg, HostSlice::from_mut_slice(&mut ct), HostSlice::from_mut_slice(&mut ss_enc), ).unwrap(); // Decapsulation decapsulate::( HostSlice::from_slice(&sk), HostSlice::from_slice(&ct), &cfg, HostSlice::from_mut_slice(&mut ss_dec), ).unwrap(); assert_eq!(ss_enc, ss_dec); println!("{} successful KEM operations!", BATCH); } ``` -------------------------------- ### Run ICICLE Example with CPU or CUDA Backend Source: https://github.com/ingonyama-zk/icicle/blob/main/examples/rust/hash-and-merkle/README.md Commands to execute the ICICLE examples using either the CPU or CUDA backend. Specify the CUDA backend installation directory when using the CUDA option. ```sh # For CPU ./run.sh -d CPU ``` ```sh # For CUDA ./run.sh -d CUDA -b /path/to/cuda/backend/install/dir ``` -------------------------------- ### Example: Binary Merkle Tree with Keccak-256 (Golang) Source: https://github.com/ingonyama-zk/icicle/blob/main/docs/versioned_docs/version-4.0.0/api/golang-bindings/merkle.md Demonstrates creating and building a binary Merkle tree with 5 layers using Keccak-256 hashing. Requires `go` version 1.22 or higher. ```go import ( "github.com/ingonyama-zk/icicle/v3/wrappers/golang/core" "github.com/ingonyama-zk/icicle/v3/wrappers/golang/hash" merkletree "github.com/ingonyama-zk/icicle/v3/wrappers/golang/merkle-tree" ) leafSize := 1024 maxInputSize := leafSize * 16 input := make([]byte, maxInputSize) hasher, _ := hash.NewKeccak256Hasher(uint64(leafSize)) compress, _ := hash.NewKeccak256Hasher(2 * hasher.OutputSize()) layerHashers := []hash.Hasher{hasher, compress, compress, compress, compress} mt, _ := merkletree.CreateMerkleTree(layerHashers, uint64(leafSize), 0 /* min layer to store */) merkletree.BuildMerkleTree[byte](&mt, core.HostSliceFromElements(input), core.GetDefaultMerkleTreeConfig()) ``` -------------------------------- ### Retrieve Merkle Root Source: https://github.com/ingonyama-zk/icicle/blob/main/docs/versioned_docs/version-4.0.0/api/rust-bindings/merkle.md Use this method to get the Merkle root hash of the tree. The root can then be serialized, for example, to be included in a proof. ```rust struct MerkleTree{ /// Retrieve the root of the Merkle tree. /// /// # Returns /// A reference to the root hash. pub fn get_root(&self) -> Result<&[T], IcicleError>; } let commitment: &[u8] = merkle_tree .get_root() .unwrap(); println!("Commitment: {:?}", commitment); ``` -------------------------------- ### Example: CUDA Backend NTT with Custom Configuration Source: https://github.com/ingonyama-zk/icicle/blob/main/docs/versioned_docs/version-4.0.0/api/cpp/ntt.md Demonstrates how to use the ntt function with custom configurations for the CUDA backend, including fast twiddles and mixed-radix algorithm selection. ```cpp #include "icicle/backend/ntt_config.h" // allocate and init input/output int batch_size = /*...*/; int log_ntt_size = /*...*/; int ntt_size = 1 << log_ntt_size; auto input = std::make_unique(batch_size * ntt_size); auto output = std::make_unique(batch_size * ntt_size); initialize_input(ntt_size, batch_size, input.get()); // Initialize NTT domain with fast twiddles (CUDA backend) scalar_t basic_root = scalar_t::omega(log_ntt_size); auto ntt_init_domain_cfg = default_ntt_init_domain_config(); ConfigExtension backend_cfg_ext; backend_cfg_ext.set(CudaBackendConfig::CUDA_NTT_FAST_TWIDDLES_MODE, true); ntt_init_domain_cfg.ext = &backend_cfg_ext; ntt_init_domain(basic_root, ntt_init_domain_cfg); // ntt configuration NTTConfig config = default_ntt_config(); ConfigExtension ntt_cfg_ext; config.batch_size = batch_size; // Compute NTT with explicit selection of Mixed-Radix algorithm. ntt_cfg_ext.set(CudaBackendConfig::CUDA_NTT_ALGORITHM, CudaBackendConfig::NttAlgorithm::MixedRadix); config.ext = &ntt_cfg_ext; ntt(input.get(), ntt_size, NTTDir::kForward, config, output.get()); ``` -------------------------------- ### Get Default VecOps Configuration Source: https://github.com/ingonyama-zk/icicle/blob/main/docs/versioned_docs/version-4.0.0/api/golang-bindings/vec-ops.md Obtain a default `VecOpsConfig` to customize vector operation parameters. This provides a starting point for configuration. ```go func DefaultVecOpsConfig() VecOpsConfig ``` -------------------------------- ### Get Default MSM Configuration Source: https://github.com/ingonyama-zk/icicle/blob/main/docs/versioned_docs/version-4.0.0/api/golang-bindings/msm.md Use `GetDefaultMSMConfig` to initialize an `MSMConfig` with sensible defaults. This function provides a starting point that can be modified to suit specific performance requirements or hardware configurations. ```go func GetDefaultMSMConfig() MSMConfig ``` -------------------------------- ### Prepare CUDA Backend Directory Source: https://github.com/ingonyama-zk/icicle/blob/main/docs/versioned_docs/version-4.0.0/start/integration-&-support/colab-instructions.md Creates and navigates into a directory for downloading the CUDA backend. This organizes the backend files for subsequent steps. ```sh %cd /content !rm -rf cuda_backend/ !mkdir cuda_backend %cd cuda_backend ``` -------------------------------- ### Multi-Scalar Multiplication (MSM) Example in C++ Source: https://github.com/ingonyama-zk/icicle/blob/main/docs/versioned_docs/version-4.0.0/start/programmers_guide/cpp.md Demonstrates the usage of the ICICLE MSM API for cryptographic operations. It includes device selection (CUDA or CPU), input setup, random data generation, MSM execution with device scalars, and error handling. ```cpp #include #include "icicle/runtime.h" #include "icicle/curves/params/bn254.h" #include "icicle/msm.h" using namespace bn254; int main() { // Load installed backends icicle_load_backend_from_env_or_default(); // trying to choose CUDA if available, or fallback to CPU otherwise (default device) const bool is_cuda_device_available = (eIcicleError::SUCCESS == icicle_is_device_available("CUDA")); if (is_cuda_device_available) { Device device = {"CUDA", 0}; // GPU-0 ICICLE_CHECK(icicle_set_device(device)); // ICICLE_CHECK asserts that the api call returns eIcicleError::SUCCESS } // else we stay on CPU backend // Setup inputs int msm_size = 1024; auto scalars = std::make_unique(msm_size); auto points = std::make_unique(msm_size); projective_t result; // Generate random inputs scalar_t::rand_host_many(scalars.get(), msm_size); projective_t::rand_host_many(points.get(), msm_size); // (optional) copy scalars to device memory explicitly scalar_t* scalars_d = nullptr; auto err = icicle_malloc((void**)&scalars_d, sizeof(scalar_t) * msm_size); // Note: need to test err and make sure no errors occurred err = icicle_copy(scalars_d, scalars.get(), sizeof(scalar_t) * msm_size); // MSM configuration MSMConfig config = default_msm_config(); // tell icicle that the scalars are on device. Note that EC points and result are on host memory in this example. config.are_scalars_on_device = true; // Execute the MSM kernel (on the current device) eIcicleError result_code = msm(scalars_d, points.get(), msm_size, config, &result); // OR call bn254_msm(scalars_d, points.get(), msm_size, config, &result); // Free the device memory icicle_free(scalars_d); // Check for errors if (result_code == eIcicleError::SUCCESS) { std::cout << "MSM result: " << projective_t::to_affine(result) << std::endl; } else { std::cerr << "MSM computation failed with error: " << get_error_string(result_code) << std::endl; } return 0; } ``` -------------------------------- ### Find and Fetch Taskflow Dependency Source: https://github.com/ingonyama-zk/icicle/blob/main/icicle/backend/cpu/CMakeLists.txt This CMake code block handles finding an existing Taskflow installation or fetching and building it if not found. It configures Taskflow to disable unnecessary components like benchmarks, profilers, and examples to reduce build time and size. Ensure Taskflow is available or will be fetched correctly. ```cmake cmake_minimum_required(VERSION 3.18) # Find Taskflow package message(DEBUG "Checking for Taskflow v3.8.0") find_package(Taskflow 3.8.0 EXACT QUIET) if(Taskflow_FOUND) message(STATUS "Found Taskflow v${Taskflow_VERSION}, using existing installation.") # Use icicle_device as interface for TaskFlow headers target_link_libraries(icicle_device INTERFACE Taskflow::Taskflow) else() message(STATUS "Taskflow not found locally. Fetching Taskflow v3.8.0 (CPU backend)") message(WARNING "Unless this project is itself installed, Taskflow will not be cached for future builds (and may therefore be re-fetched).") include(FetchContent) # Temporarily redefine set message log level to WARNING for fetched content set(ORIG_CMAKE_MESSAGE_LOG_LEVEL "${CMAKE_MESSAGE_LOG_LEVEL}") set(CMAKE_MESSAGE_LOG_LEVEL "WARNING") FetchContent_Declare( Taskflow GIT_REPOSITORY https://github.com/taskflow/taskflow.git GIT_TAG d8c49c64b4ee5015a3f1c0a42748fa7a2bf5529e # v3.8.0 GIT_SHALLOW TRUE ) # Disable unnecessary components set(TF_BUILD_BENCHMARKS OFF CACHE BOOL "Disable Taskflow benchmarks" FORCE) set(TF_BUILD_PROFILER OFF CACHE BOOL "Disable Taskflow profiler" FORCE) set(TF_BUILD_CUDA OFF CACHE BOOL "Disable Taskflow CUDA support" FORCE) set(TF_BUILD_SYCL OFF CACHE BOOL "Disable Taskflow SYCL support" FORCE) set(TF_BUILD_TESTS OFF CACHE BOOL "Disable Taskflow tests" FORCE) set(TF_BUILD_EXAMPLES OFF CACHE BOOL "Disable Taskflow examples" FORCE) FetchContent_MakeAvailable(Taskflow) # Use icicle_device as interface for TaskFlow headers target_include_directories(icicle_device INTERFACE ${Taskflow_SOURCE_DIR}) # Restore the original message log level set(CMAKE_MESSAGE_LOG_LEVEL "${ORIG_CMAKE_MESSAGE_LOG_LEVEL}") endif() ``` -------------------------------- ### ML-KEM Key Generation, Encapsulation, and Decapsulation Example (Kyber768) Source: https://github.com/ingonyama-zk/icicle/blob/main/docs/versioned_docs/version-4.0.0/api/cpp/lattice/pqc_ml_kem.md Demonstrates a full ML-KEM workflow using Kyber768 parameters, including key generation, encapsulation, and decapsulation. Assumes `TypeParam` is defined and `this->random_entropy` is available. ```cpp #include "icicle/pqc/ml_kem.h" using namespace icicle::pqc::ml_kem; int main() { const int batch_size = 1 << 12; // Config MlKemConfig config; config.batch_size = batch_size; // Allocate buffers auto entropy = this->random_entropy(batch_size * ENTROPY_BYTES); std::vector public_key(batch_size * TypeParam::PUBLIC_KEY_BYTES); std::vector secret_key(batch_size * TypeParam::SECRET_KEY_BYTES); std::vector ciphertext(batch_size * TypeParam::CIPHERTEXT_BYTES); std::vector shared_secret_enc(batch_size * TypeParam::SHARED_SECRET_BYTES); std::vector shared_secret_dec(batch_size * TypeParam::SHARED_SECRET_BYTES); auto message = this->random_entropy(batch_size * MESSAGE_BYTES); // Key generation auto err = keygen(entropy.data(), config, public_key.data(), secret_key.data()); // Encapsulation err = encapsulate(message.data(), public_key.data(), config, ciphertext.data(), shared_secret_enc.data()); // Decapsulation err = decapsulate(secret_key.data(), ciphertext.data(), config, shared_secret_dec.data()); } ``` -------------------------------- ### Verify Rust and Cargo Installation Source: https://github.com/ingonyama-zk/icicle/blob/main/docs/versioned_docs/version-4.0.0/start/integration-&-support/colab-instructions.md Checks if Rust and Cargo have been installed correctly by printing their version numbers. This helps confirm the installation was successful. ```sh !rustc --version !cargo --version ``` -------------------------------- ### Example: Using Coefficients View (C++) Source: https://github.com/ingonyama-zk/icicle/blob/main/docs/versioned_docs/version-4.0.0/api/cpp/polynomials/overview.md Demonstrates obtaining a coefficients view and passing its raw pointer to a GPU-accelerated function. Ensure the view is valid before use, especially after modifications to the original polynomial. ```cpp auto [coeffs_view, size, device_id] = polynomial.get_coefficients_view(); // Use coeffs_view in a computational routine that requires direct access to polynomial coefficients // Example: Passing the view to a GPU-accelerated function gpu_accelerated_function(coeffs_view.get(),...); ``` -------------------------------- ### Install ICICLE Backend in Custom Location Source: https://github.com/ingonyama-zk/icicle/blob/main/examples/rust/install-and-use-icicle/README.md Installs the ICICLE CUDA backend to a custom directory and sets the ICICLE_BACKEND_INSTALL_DIR environment variable. This is an alternative to installing in /opt. ```bash mkdir -p /custom/path tar xzvf icicle30-ubuntu22-cuda122.tar.gz -C /custom/path ``` ```bash export ICICLE_BACKEND_INSTALL_DIR=/custom/path/icicle/lib/backend ``` -------------------------------- ### v4 Program API Example Source: https://github.com/ingonyama-zk/icicle/blob/main/docs/versioned_docs/version-4.0.0/start/integration-&-support/migrate_from_v3.md Demonstrates creating and executing programs, including returning value programs, using the v4 Program API. ```rust use icicle_bn254::curve::ScalarField; use icicle_core::program::{Program, ReturningValueProgram}; use icicle_bn254::program::stark252::{FieldProgram, FieldReturningValueProgram}; // Create program let program = FieldProgram::new(|symbols| { // Program logic here }, nof_params)?; // Execute program program.execute_program(&mut vec_data, &config)?; // Create returning value program let returning_program = FieldReturningValueProgram::new(|symbols| -> symbol { // Program logic here result_symbol }, nof_params)?; ``` -------------------------------- ### Example: Generating a Sumcheck Proof Source: https://github.com/ingonyama-zk/icicle/blob/main/docs/versioned_docs/version-4.0.0/api/cpp/sumcheck.md Demonstrates generating a Sumcheck proof using default configurations for the transcript and combine function. Ensure MLE polynomials, size, and claimed sum are correctly provided. ```cpp auto prover_sumcheck = create_sumcheck(); SumcheckTranscriptConfig transcript_config; // default configuration ReturningValueProgram combine_func(EQ_X_AB_MINUS_C); SumcheckConfig sumcheck_config; SumcheckProof sumcheck_proof; ICICLE_CHECK(prover_sumcheck.get_proof( mle_polynomials, mle_poly_size, claimed_sum, combine_func, std::move(transcript_config), sumcheck_config, sumcheck_proof)); ``` -------------------------------- ### Build Binary Merkle Tree with Keccak-256 Source: https://github.com/ingonyama-zk/icicle/blob/main/docs/versioned_docs/version-4.0.0/api/cpp/merkle.md Example demonstrating the construction of a binary Merkle tree with 5 layers using Keccak-256 for hashing. Input data is prepared and the tree is built with default configuration. ```cpp const uint64_t leaf_size = 1024; // Allocate a dummy input. It can be any type as long as the total size matches. const uint32_t max_input_size = leaf_size * 16; auto input = std::make_unique(max_input_size / sizeof(uint64_t)); // Define hashers auto hash = Keccak256::create(leaf_size); // hash 1KB -> 32B auto compress = Keccak256::create(2 * hasher.output_size()); // hash every 64B to 32B // Construct the tree using the layer hashers and leaf-size std::vector hashers = {hasher, compress, compress, compress, compress}; auto merkle_tree = MerkleTree::create(hashers, leaf_size); // compute the tree merkle_tree.build(input.get(), max_input_size / sizeof(uint64_t), default_merkle_tree_config()); ``` -------------------------------- ### Install Project Dependencies Source: https://github.com/ingonyama-zk/icicle/blob/main/docs/README.md Run this command in your terminal to install all necessary project dependencies for Docusaurus. ```sh npm install ``` -------------------------------- ### Setup PQC Target and Package Source: https://github.com/ingonyama-zk/icicle/blob/main/icicle/CMakeLists.txt Configures the Post-Quantum Cryptography (PQC) target if the PQC option is enabled. Optionally sets up a PQC package target if PQC_PACKAGE is also enabled. ```cmake if (PQC) setup_pqc_target() if (PQC_PACKAGE) setup_pqc_package_target() endif() endif() ``` -------------------------------- ### Matrix Multiplication Example Source: https://github.com/ingonyama-zk/icicle/blob/main/docs/versioned_docs/version-4.0.0/api/rust-bindings/matrix_ops.md Example demonstrating how to multiply two BN254 matrices entirely on the GPU. ```APIDOC ## Example Multiply two random BN254 matrices entirely on the GPU and read the result back to the host. (All buffers can be on host or device; you can mix and match as needed.) ```rust use icicle_bn254::field::ScalarField; use icicle_core::matrix_ops::{matmul, MatMulConfig}; use icicle_core::vec_ops::VecOpsConfig; use icicle_runtime::memory::{DeviceVec, HostSlice}; use icicle_core::traits::GenerateRandom; const N: usize = 512; // We will compute C = A × B where A,B are N×N // 1. Generate random data on the host let a_host = ScalarField::generate_random(N * N); let b_host = ScalarField::generate_random(N * N); // 2. Move the data to device memory // 3. Allocate the result buffer on the device // 4. Perform matmul let cfg = MatMulConfig::default(); matmul(&a_dev[..], N as u32, N as u32, &b_dev[..], N as u32, N as u32, &cfg, &mut c_dev[..]).unwrap(); // Result is stored in c_dev for this example // 5. Copy the result back if needed ``` ``` -------------------------------- ### Set Installation Prefix and RPATH Source: https://github.com/ingonyama-zk/icicle/blob/main/icicle/CMakeLists.txt Configures the installation prefix for the project. If not defined, it defaults to a subdirectory within the build directory. Sets the runtime library search path (RPATH) to include the installation's lib directory. ```cmake # Define the install directory (default is /usr/local) if(NOT DEFINED CMAKE_INSTALL_PREFIX) set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install" CACHE PATH "Install path prefix") endif() message(STATUS "CMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}") set(CMAKE_INSTALL_RPATH ${CMAKE_INSTALL_PREFIX}/lib) ``` -------------------------------- ### Set ICICLE PQC Installation Directory Source: https://github.com/ingonyama-zk/icicle/blob/main/examples/c++/pqc-package/README.md Set the ICICLE_PQC_INSTALL_DIR environment variable to the directory where ICICLE PQC was installed. ```bash export ICICLE_PQC_INSTALL_DIR=/path/to/icicle/pqc/install ``` -------------------------------- ### Set Custom Installation Directory Source: https://github.com/ingonyama-zk/icicle/blob/main/docs/versioned_docs/version-4.0.0/start/programmers_guide/build_from_source.md Define an environment variable to specify a custom directory for installing ICICLE libraries. ```bash export ICICLE_INSTALL_DIR=/path/to/install/dir ``` -------------------------------- ### v3 Program API Example (VecOps) Source: https://github.com/ingonyama-zk/icicle/blob/main/docs/versioned_docs/version-4.0.0/start/integration-&-support/migrate_from_v3.md Example of creating and executing a program using the v3 VecOps API. ```rust use icicle_bn254::curve::ScalarField; use icicle_core::vec_ops::{VecOps, VecOpsConfig}; // Create program let program = ScalarField::create_program(|symbols| { // Program logic here }, nof_params)?; // Execute program ScalarField::execute_program(&program, &mut vec_data, &config)?; ``` -------------------------------- ### Install Gnark with ICICLE Support Source: https://github.com/ingonyama-zk/icicle/blob/main/docs/versioned_docs/version-4.0.0/start/integration-&-support/integrations.md Install the master branch of Gnark to include ICICLE as an indirect dependency for GPU acceleration. ```bash go get github.com/consensys/gnark@master ```