halo2curves

repository·main·Indexed 42 days ago

https://github.com/privacy-ethereum/halo2curves

Elliptic curve implementations and wrappers for the halo2 library, version 0.10.0. It provides high-performance implementations of curves including BN256, Secp256k1, Grumpkin, Secp256r1, Pluto, Eris, and T-256, optimized for ZkCrypto traits (ff, group, and pairing). The library features assembly optimizations, Serde integration, and support for projective and affine coordinate arithmetic.

Tokens
8.7K
Snippets
32
Records
43
Agent score
53%

What's inside halo2curves

  1. Overview of halo2curves

    main

    The halo2curves library provides efficient and flexible implementations of various halo2-friendly elliptic curves. It is designed to work with traits from the zkcrypto ecosystem, specifically:

    • zkcrypto/ff (Finite Fields)
    • zkcrypto/group (Groups)
    • zkcrypto/pairing (Pairings)

    Supported curves include bn256, grumpkin, secp256k1, secp256r1, pluto, eris, T-256, and grumpkin. The library features assembly optimizations for performance and supports Serde for serialization/deserialization.

  2. Control parallelism with RAYON_NUM_THREADS

    main

    The library uses rayon for parallel computation. You can control the number of threads used for parallel operations by setting the RAYON_NUM_THREADS environment variable.

    WASM Compilation Note: When compiling to WASM targets, rayon (since version 1.7) automatically falls back to requiring getrandom to function. Ensure your WASM environment is configured to support getrandom requirements.

  3. Run benchmarks for halo2curves

    main

    Benchmarks are integrated into the Rust test framework. You can run them with or without assembly optimizations using the following commands:

    Without assembly optimizations:

    $ cargo test --profile bench test_field -- --nocapture

    With assembly optimizations:

    $ cargo test --profile bench test_field --features asm -- --nocapture
  4. Configure field generation via FieldConfig macro

    main

    The halo2derive package uses a procedural macro to generate field arithmetic implementations. To use it, you must provide a FieldConfig structure within the macro call. The configuration requires specific keys for the modulus, generators, and endianness.

    Required Configuration Keys:

    • identifier: A unique name for the configuration.
    • field: The name of the struct to be generated.
    • modulus: The field modulus (provided as a hex string, e.g., "0x...").
    • mul_gen: The multiplicative generator.
    • zeta: The zeta value for small order multiplication groups.
    • endian: The byte order for serialization, must be either "little" or "big".
    • from_uniform: A list of usize values representing input sizes for FromUniformBytes implementations.
    // Note: This is a conceptual representation of the macro input structure
    // used by the `impl_field` procedural macro.
    field_macro!(
        MyFieldIdentifier,
        MyFieldStruct,
        modulus = 0x123456789abcdef...,
        mul_gen = 0x...,
        zeta = 0x...,
        endian = "little",
        from_uniform = [64, 128]
    );
  5. Understand Compressed curve point encoding

    main

    The Compressed<C> trait manages the encoding and decoding of compressed elliptic curve points. The encoding strategy depends on the CompressedFlagConfig associated with the curve.

    Supported Encoding Configurations

    • Extra: Used by Secp256k1 and Secp256r1. Includes an extra byte for flags (sign, identity). The flag byte is the most significant byte.
    • SingleSpare: Used by Pasta curves. Uses a single spare bit for the sign.
    • TwoSpare: Used by BN254. Uses two spare bits (sign, identity).
    • ThreeSpare: Used by BLS12-{381, 377}. Uses three spare bits (is_compressed, sign, identity).

    Key Operations

    • encode(&c): Encodes a curve point c into a compressed representation, setting flags for identity, sign, and compression status.
    • decode(self): Decodes a compressed representation back into a curve point. Returns a subtle::CtOption<C> to allow for constant-time validation of the point (checking sign, identity, and coordinate validity).
    • Flags: The implementation uses bit manipulation to set/get flags for sign, is_compressed, and is_identity within a designated flag byte.
  6. How the SSWU and SVDW methods work

    main

    The Suite uses two primary mathematical approaches to map field elements to curve points:

    1. SSWU (Simplified Shallue-Woestman-Ulas): Requires an Iso<C> structure which contains the curve coefficients a, b and a mapping function to transform coordinates from an isogenous curve back to the original curve.
    2. SVDW (Shallue-van de Woestijne-Delfs-Weng): Uses precomputed constants derived from the non-square element z to perform the mapping directly.

    Both methods ensure that the resulting point is a valid point on the curve C.

  7. Secp256k1 Curve Implementation

    main

    The Secp256k1 curve is implemented as a CofactorGroup. It supports standard elliptic curve operations including addition, multiplication, and negation. The implementation uses Fp for the base field and Fq for the scalar field. The curve is defined by the parameters $a=0$ and $b=7$ (standard Secp256k1).

    // The Secp256k1 implementation is provided via the new_curve_impl macro
    // which exposes Secp256k1 and Secp256k1Affine types.
  8. Available curve features and optimizations

    main

    The library provides several specialized features for cryptographic workflows:

    • Serde Integration: Supports Serialize and Deserialize traits for field and group elements.
    • Hash to Curve: Implemented for bn256::G1 and grumpkin::G1 to enable efficient hash-and-sign signature schemes.
    • Lookup Table: A pre-computed lookup table is available for bn256::Fr to accelerate conversion from u16 to Montgomery representation.
  9. Use the hash_to_curve helper function

    main

    The hash_to_curve function is a convenience wrapper that returns a boxed closure. This closure can be called repeatedly with different messages to obtain points on the curve, all mapped under the same domain_prefix and Suite configuration.

    Signature: pub fn hash_to_curve<'a, C, D, const L: usize>(domain_prefix: &'a str, suite: Suite<C, D, L>) -> Box<dyn Fn(&[u8]) -> C + 'a>

    let hasher = hash_to_curve("MY_DOMAIN", suite);
    let point = hasher(b"my message");
  10. Perform recursive butterfly arithmetic with `recursive_butterfly_arithmetic`

    main

    The recursive_butterfly_arithmetic function is a specialized implementation used by best_fft to perform the FFT using a recursive approach. This is typically triggered when the workload is large enough to benefit from parallel execution via plonky2_maybe_rayon::join.

    // Signature:
    // pub fn recursive_butterfly_arithmetic<Scalar: Field, G: FftGroup<Scalar>>(
    //     a: &mut [G],
    //     n: usize,
    //     twiddle_chunk: usize,
    //     twiddles: &[Scalar],
    // )
  11. Use the CurveAffine trait for affine coordinate operations

    main

    The CurveAffine trait is the affine counterpart to CurveExt. It is primarily used for serialization, memory storage, and inspecting the $(x, y)$ coordinates of a point. It implements PrimeCurveAffine and provides methods to interact with the curve's base and scalar fields in their affine form.

    Key capabilities include:

    • Coordinate Inspection: Retrieve coordinates via .coordinates(), which returns a CtOption<Coordinates<Self>> (returning None if the point is the identity).
    • Point Creation: Create a point from $(x, y)$ coordinates using .from_xy(x, y).
    • Validation: Check if a point is on the curve using .is_on_curve().
    • Curve Constants: Access curve constants $a$ and $b$ via .a() and .b().
  12. Hash to Secp256k1 Curve

    main

    The library provides a mechanism to map arbitrary messages to points on the Secp256k1 curve using the hash_to_curve function. This implementation follows the secp256k1_XMD:SHA-256_SSWU_RO_ suite, which utilizes the Simplified Swapping Weil (SSWU) method and an isogeny map for efficiency and security.

    To use this, you provide a domain_prefix (a string) and a message (a byte slice). The function returns a closure that can be used to perform the actual hashing.

    // Note: hash_to_curve is marked as pub(crate) in this file, 
    // implying it is intended for use within the crate or via exported wrappers.
    // The conceptual usage pattern is:
    // let hasher = hash_to_curve("domain_prefix", suite);
    // let point = hasher(message_bytes);