Winterfell STARK Prover and Verifier

repository·main·Indexed 21 days ago

https://github.com/facebook/winterfell

A high-performance STARK prover and verifier for arbitrary computations. It supports multi-threading, customizable cryptography, and WebAssembly targets. The library includes the winter-air crate for defining computations via the Air trait (Algebraic Intermediate Representation) and the winter-crypto crate providing hash functions (SHA3, BLAKE3, Rescue Prime), Merkle trees with batch proof support, and no_std compatibility.

Tokens
64.1K
Snippets
199
Records
261
Agent score
74%

What's inside Winterfell

  1. Overview of Winterfell STARK prover and verifier

    main

    Winterfell is a STARK (Scalable Transparent Argument of Knowledge) prover and verifier designed for arbitrary computations. It allows for the creation of efficiently verifiable proofs that a specific computation was executed correctly without requiring a trusted setup.

    Warning: This is a research project. It has not been audited and may contain bugs or security flaws. It is NOT intended for production use.

  2. Use the Winterfell crate for STARK prover and verifier

    main
    The winterfell crate serves as a top-level entry point that re-exports the core components of the Winterfell STARK system. Instead of importing individual sub-crates, you can use winterfell to access the functionality defined in the prover and verifier crates.
  3. Use Winter rand utils for random value generation

    main

    The winter-rand-utils crate provides functions for generating random values. These utilities are specifically designed for use in tests, benchmarks, and examples within the Winterfell ecosystem.

    Important Note on WebAssembly (Wasm): All functions in this crate are omitted when compiling to a WebAssembly target. If your project targets Wasm, you cannot use these utilities.

  4. Represent an execution trace using TraceTable

    main

    An execution trace is a 2D matrix where rows are time steps and columns are algebraic registers. While you can implement the Trace trait on any custom struct, Winterfell provides the TraceTable struct for convenience.

    Option 1: Manual Initialization

    Use TraceTable::init() by passing a set of vectors, where each vector represents a column. Requirements:

    1. All columns must have the same length.
    2. The length must be a power of two.

    Use TraceTable::new(width, length) to allocate memory, then use the fill() method. fill() takes two closures:

    1. An initializer for the first row (the initial state).
    2. A state transition function that receives the previous state and updates it to the next state.

    This approach is simpler and facilitates concurrent trace generation.

    // Example concept for TraceTable initialization
    let mut trace = TraceTable::new(width, length);
    trace.fill(
        || { /* initialize first row */ },
        |prev_state| { /* compute next state from prev_state */ }
    );
  5. How AIR-based examples are structured

    main

    The core logic for each example is located in its air.rs file. These files define the computation using the Algebraic Intermediate Representation (AIR) framework. An AIR implementation typically consists of two main components:

    1. build_trace() function: Responsible for generating the execution trace for the specific computation.
    2. Air trait implementation: Describes the algebraic constraints that define the computation.

    Understanding these two components is key to implementing custom computations in Winterfell.

  6. Enable concurrent execution in Winter utils

    main

    When the concurrent feature is enabled, the crate uses the rayon crate to perform parallel execution for certain functions, specifically transpose_slice().

    To control the level of parallelism, you can set the RAYON_NUM_THREADS environment variable. If not set, it defaults to the number of logical cores available on the machine.

    # Example: Running with a specific number of threads
    RAYON_NUM_THREADS=4 cargo run
  7. Use finite fields for STARK arithmetic

    main

    The src/field module provides arithmetic operations in STARK-friendly finite fields. Supported operations include basic arithmetic (addition, multiplication, subtraction, division, inversion), drawing random/pseudo-random elements, and computing roots of unity.

    Available Field Implementations

    FieldModulusSecurity Notes
    f128$2^{128} - 45 imes 2^{40} + 1$Sub-optimal performance. Provides ~100 bits of security. For higher security, use a quadratic extension.
    f62$2^{62} - 111 imes 2^{39} + 1$Fast modular arithmetic (branchless). Provides ~100 bits of security. Use quadratic extensions for higher security, or cubic extensions for even higher levels.
    f64$2^{64} - 2^{32} + 1$Fast, constant-time implementation. Provides ~100 bits of security. Use quadratic extensions for higher security, or cubic extensions for even higher levels.
  8. Define trace assertions for boundary constraints

    main

    Assertions specify that certain cells in an execution trace must contain specific values. In Winterfell, these are internally converted into boundary constraints. Every computation must implement get_assertions() and provide at least one assertion.

    There are three types of assertions:

    1. Single Assertion: Specifies a single cell at a specific column and step must equal a value (e.g., column 0, step 0 == 1).
    2. Periodic Assertion: Specifies values in a column at specified intervals must equal certain values (e.g., column 0, steps 0, 8, 16, 24... == 2).
    3. Sequence Assertion: Specifies values in a column at intervals must follow a provided sequence (e.g., column 0, step 0 1, step 8 2, step 16 == 3...).
  9. Create extension fields for higher security

    main

    To achieve security levels higher than ~100 bits, you can use quadratic or cubic extensions of the base fields. The library provides a generic way to create these by implementing the ExtensibleField trait for degrees 2 and 3.

    Irreducible Polynomials used for extensions

    Quadratic Extensions ($x^2$):

    • f62: $x^2 - x - 1$
    • f64: $x^2 - x + 2$
    • f128: $x^2 - x - 1$

    Cubic Extensions ($x^3$):

    • f62: $x^3 + 2x + 2$
    • f64: $x^3 - x - 1$
    • f128: Not supported
  10. Use Fast Fourier Transform (FFT) for polynomial operations

    main

    The src/fft module implements the Number-theoretic transform (FFT) in a prime field.

    Use this to perform polynomial interpolation and evaluation in $O(n ext{ log } n)$ time. This is applicable as long as the domain of the polynomial is a multiplicative subgroup with a size that is a power of 2.

  11. Understand Winterfell prover performance characteristics

    main

    Winterfell's performance is influenced by the computation's nature, AIR encoding efficiency, proof generation parameters, and hardware. Key performance metrics include:

    • Trace time: The time to generate an execution trace. This can often be parallelized if the computation allows it.
    • Proving time: The time required to generate the STARK proof. Most steps in the STARK proof generation process can be parallelized.
    • Proof size: The size of the generated proof. In STARKs, this grows logarithmically with the size of the computation.
    • Verifier time: The time required to verify a proof. This also grows logarithmically with the size of the computation.
    • Prover RAM: The memory consumed during proof generation, which typically grows linearly with the size of the computation.

    Users can dynamically trade off proof size, security level, and proving time based on their requirements.

  12. Perform polynomial operations

    main

    The src/polynom module provides core polynomial functionality:

    • Evaluation: Evaluate a polynomial at a single point.
    • Interpolation: Interpolate a polynomial from a set of points using Lagrange interpolation.
    • Arithmetic: Addition, multiplication, subtraction, and division of polynomials.
    • Division: Synthetic polynomial division using Ruffini's rule.