ICICLE Documentation

repository·main·Indexed 19 days ago

https://github.com/ingonyama-zk/icicle

A high-performance cryptographic acceleration library designed to optimize Zero Knowledge Proof (ZKP) computations across CPUs, GPUs, and other hardware accelerators. The library provides C++ APIs for operations such as Multi-Scalar Multiplication (MSM) and Number-Theoretic Transform (NTT), with support for backends including CUDA and METAL.

Tokens
99.1K
Snippets
268
Records
366
Agent score
66%

What's inside ICICLE

  1. Overview of ICICLE Hashing Logic

    main
    ICICLE provides a flexible hashing system optimized for both CPU and GPU (via CUDA). It supports general-purpose cryptographic hashes and arithmetization-friendly hashes designed for Zero-Knowledge Proofs (ZKPs). The system handles data as strings, arrays, or field elements, with output buffers that automatically adapt to the hashed data size. For large datasets, ICICLE supports batch hashing to enable parallel computation on the GPU.
  2. Introduction to ICICLE

    main

    ICICLE is a high-performance, versatile cryptography library designed to accelerate core cryptographic building blocks. It features a multi-backend architecture that allows developers to leverage various hardware accelerators for optimized performance.

    Key Capabilities

    • High-Speed Cryptography: Optimized performance for core primitives used in modern cryptographic protocols.
    • Modular and Extensible: Includes libraries for various fields and curves, with support for adding custom backends or primitives.
    • Cross-Platform & Cross-Language: Supports C++, Rust, and Go, with potential Python support. It can run on CPU and deploy to diverse backends including CUDA, Metal, and upcoming support for WebGPU, Vulkan, and ZPU.

    Common Use Cases

    • Boost Prover Performance: Integrate into existing frameworks like Gnark or Halo2 for GPU acceleration without code changes.
    • Selective Acceleration: Target specific bottlenecks in an existing prover for optimization without a full rewrite.
    • Build Custom Provers: Use ICICLE as a foundation for high-performance, scalable systems that scale across multiple GPUs and machines.
    • Rapid Prototyping: Quickly implement cryptographic primitives (e.g., KZG commitment schemes) using Rust or Go bindings.
  3. Explore ICICLE core APIs for C++, Go, and Rust

    main

    ICICLE provides high-performance core APIs for cryptographic primitives, specifically focusing on:

    • MSM (Multi-Scalar Multiplication)
    • NTT (Number Theoretic Transform)
    • Hashing primitives

    Developers can access these APIs through dedicated language-specific overviews for C++, Go, and Rust. Each language implementation includes specific examples to help you integrate these primitives into your workflow.

  4. Use ML-KEM (Kyber) Rust bindings

    main

    The icicle-ml-kem crate provides a Rust wrapper for Icicle's batched ML-KEM (Kyber) implementation. It supports both host and device memory and provides three primary operations: key pair generation, encapsulation, and decapsulation. All operations are batched, meaning you provide buffers sized for batch_size number of operations.

    use icicle_ml_kem as mlkem;
    use icicle_ml_kem::{keygen, encapsulate, decapsulate};
    // ... usage of keygen, encapsulate, and decapsulate
  5. Polynomial API capabilities in ICICLE

    main

    The ICICLE Polynomial API provides a suite of operations for polynomial arithmetic, which are essential for Zero-Knowledge Proof (ZKP) construction and verification.

    Key operations available in the examples include:

    Construction and Evaluation

    • example_evaluate: Create a polynomial from coefficients and evaluate it at a random point.
    • example_clone: Create a separate copy of an existing polynomial.
    • example_from_rou: Reconstruct a polynomial from values at the roots of unity (ROU).
    • example_monomials: Add or subtract a monomial (a single term consisting of a constant coefficient and a variable raised to a power) to a polynomial.

    Arithmetic Operations

    • Addition: Supports both standard (example_addition) and in-place (example_addition_inplace) addition.
    • Multiplication: Includes product of two polynomials (example_multiplication) and product of a scalar and a polynomial (example_multiplicationScalar).
    • Division: Includes different flavors of division (example_divisionSmall, example_divisionLarge) and division by a vanishing polynomial (example_divideByVanishingPolynomial).

    Transformation and Slicing

    • example_EvenOdd: Extracts even or odd coefficients from a polynomial.
    • example_Slice: A generalized version of even/odd methods that keeps coefficients based on a specific origin (offset) and stride.

    Memory and Data Management

    • example_ReadCoeffsToHost: Downloads polynomial coefficients from the GPU to the host. Note that ICICLE keeps polynomials on the GPU by default; host-side operations require this explicit transfer.
    • example_DeviceMemoryView: Provides device-memory views of polynomials, allowing them to be passed to other GPU functions (e.g., committing coefficients to a Merkle tree without involving the host).
  6. What is the Sumcheck protocol in ICICLE?

    main

    The Sumcheck protocol allows a Prover to prove to a Verifier that the sum of a multilinear polynomial (or a combination of multiple multilinear polynomials via a combine function) over a Boolean hypercube equals a specific scalar value $C$.

    ICICLE's implementation is non-interactive (using a Fiat-Shamir scheme) and supports both CPU and CUDA backends. Polynomials must be provided in MLE (evaluation representation) form.

    Key Constraints:

    • Polynomial Size: Must be a power of 2.
    • Memory Limits: The maximum polynomial size ($2^n$) is limited by the device memory (CPU/GPU) and the number of polynomials being processed.
    • Extension Fields: The current implementation does not support generating challenges ($\alpha$) in an extension field (set use_extension_field to false).
  7. Overview of Number Theoretic Transform (NTT)

    main

    The Number Theoretic Transform (NTT) is a variant of the Fourier Transform used over finite fields (integers modulo a prime $p$). It is primarily used for efficient polynomial multiplication in cryptography and modular arithmetic applications.

    Key Mathematical Requirements

    • Sequence Size ($N$): The input sequence size must be a power of 2.
    • Prime Modulo ($p$): The prime $p$ must satisfy $p = kN + 1$ for some integer $k$ to ensure the existence of $N$th roots of unity.
    • Root of Unity ($\omega$): A primitive $N$th root of unity modulo $p$ is required.

    Operations

    • NTT: Transforms a sequence $a_n$ into a frequency domain sequence $A_k$ using the formula $A_k = \sum_{n=0}^{N-1} a_n \cdot \omega^{nk} \pmod p$.
    • INTT (Inverse NTT): The inverse operation used to reconstruct the original sequence from the NTT output.
  8. Understand the ICICLE Program abstraction

    main

    The Program class allows you to define arithmetic expressions on vector elements. ICICLE compiles these expressions into a fused implementation for various backends, which helps solve memory bottlenecks and allows for customized algorithms (like sumcheck).

    Key constraints:

    • Programs can only create element-wise lambda functions.
    • The defined function describes arithmetic operations to be performed in series.
    • Control flow (loops, conditions) is not parsed. Instead, the computation follows the exact execution path taken during the tracing phase, which determines the final computation performed.
  9. Manage active and default devices

    main

    ICICLE allows you to manage which device (e.g., a specific CUDA GPU) is used for computations.

    • Default Device: Set once from the main thread using icicle_set_default_device(device). This device is used by all threads unless specified otherwise.
    • Active Device: Set a specific device for the current thread using icicle_set_device(device). Use this if a thread needs to work on a different device than the default.
    • Querying: Use icicle_get_active_device(device) to retrieve the current thread's device.

    icicle::Device is typically initialized as {"CUDA", 0} for the first GPU.

    icicle::Device device = {"CUDA", 0};
    
    // Set for all threads (do this once in main)
    eIcicleError result = icicle_set_default_device(device);
    
    // Set for the current thread
    eIcicleError result = icicle_set_device(device);
    
    // Query current device
    eIcicleError result = icicle_get_active_device(device);
  10. Compare CUDA-PQC and Closed CUDA backends

    main

    ICICLE supports multiple backends that coexist as distinct devices. The CUDA-PQC backend is an open-source, license-free alternative specifically optimized for Post-Quantum Cryptography (PQC) functionality, whereas the CUDA backend is closed-source and supports the full suite of ICICLE APIs.

    | Feature | CUDA-PQC Backend | Closed CUDA Backend |
    |------------------------|------------------------|------------------------|
    | License required | ❌ No | ✅ Yes (license checked) |
    | Source available | ✅ Open-source | ❌ Closed-source |
    | General ICICLE APIs | ❌ Not supported | ✅ Fully supported |
    | PQC APIs | ✅ Supported | ✅ Supported |
    | Registration mechanism | ✅ Statically linked | ✅ Dynamically loaded |