ark-groth16

repository·master·Indexed 43 days ago

https://github.com/arkworks-rs/groth16

An efficient implementation of the Groth16 zkSNARK proof system, part of the arkworks ecosystem of Rust libraries. Version 0.6.0 provides tools for the full lifecycle of zero-knowledge proofs, including setup, proving, and verification. It includes support for representing proofs and verifying keys as circuit variables via ProofVar and VerifyingKeyVar for recursive SNARKs, as well as the R1CSToQAP trait for reducing Rank-1 Constraint Systems to Quadratic Arithmetic Programs.

Tokens
3.5K
Snippets
9
Records
21
Agent score
55%

What's inside ark-groth16

  1. Install and build ark-groth16

    master

    The ark-groth16 library requires the stable Rust toolchain. Follow these steps to set up your environment and build the library from source.

    Prerequisites

    Install rustup from https://rustup.rs/ or via your platform's package manager, then install the stable toolchain:

    rustup install stable

    Build Steps

    Clone the repository and use cargo to build the release version:

    git clone https://github.com/arkworks-rs/groth16.git
    cd groth16
    cargo build --release
    rustup install stable
    git clone https://github.com/arkworks-rs/groth16.git
    cd groth16
    cargo build --release
  2. Represent Groth16 proofs and verifying keys as circuit variables

    master

    When building circuits that need to verify Groth16 proofs (e.g., for recursive SNARKs or proof composition), you cannot use native Groth16 types directly. Instead, you must use the variable representations provided in constraints.rs.

    These types allow you to allocate the proof and verifying key elements into the constraint system as R1CS variables:

    • ProofVar<E, P>: Represents a Groth16 proof consisting of elements a (G1), b (G2), and c (G1).
    • VerifyingKeyVar<E, P>: Represents the Groth16 verifying key, including alpha_g1, beta_g2, gamma_g2, delta_g2, and the gamma_abc_g1 vector.
    • PreparedVerifyingKeyVar<E, P>: A preprocessed version of the verifying key optimized for the verification pairing operations.
  3. Convert R1CS to QAP using the R1CSToQAP trait

    master

    The R1CSToQAP trait provides methods to reduce a Rank-1 Constraint System (R1CS) into a Quadratic Arithmetic Program (QAP), which is a necessary step for Groth16 proof generation.

    Implementations of this trait (such as LibsnarkReduction) allow you to:

    1. Map R1CS instances to QAP instances: Compute the polynomials $a(x)$, $b(x)$, and $c(x)$ and the vanishing polynomial $Z_T(x)$ from a ConstraintSystemRef.
    2. Map R1CS witnesses to QAP witnesses: Transform the assignment of variables into the QAP witness polynomial.
    3. Compute $h(x)$ query scalars: Generate the scalars used by the generator to compute the $h(x)$ polynomial, which is required for the prover to compute the quotient $h(x)t(x)/Z_T(x)$.
  4. Optimize verification with PreparedVerifyingKey

    master

    A PreparedVerifyingKey<E: Pairing> is a preprocessed version of a VerifyingKey<E>. It trades increased memory usage for faster verification by pre-calculating elements used in pairings.

    Conversion

    You can convert a standard VerifyingKey into a PreparedVerifyingKey using the From trait, which internally calls crate::prepare_verifying_key.

    Fields

    • vk: The original VerifyingKey.
    • alpha_g1_beta_g2: The precomputed pairing element e(alpha * G, beta * H) in E::TargetField.
    • gamma_g2_neg_pc: The element - gamma * H in E::G2, prepared for pairings.
    • delta_g2_neg_pc: The element - delta * H in E::G2, prepared for pairings.
    // Convert a VerifyingKey to a PreparedVerifyingKey for faster verification
    let prepared_vk: PreparedVerifyingKey<E> = VerifyingKey::default().into();
    
    // Convert back to a standard VerifyingKey
    let vk: VerifyingKey<E> = prepared_vk.into();
  5. Verify a Groth16 proof within a circuit using Groth16VerifierGadget

    master

    To verify a Groth16 proof inside another circuit, implement or use the Groth16VerifierGadget. This gadget implements the SNARKGadget trait, allowing it to be integrated into a larger constraint system.

    Workflow

    1. Allocate Variables: Use the AllocVar implementation for ProofVar, VerifyingKeyVar, and PreparedVerifyingKeyVar to bring the proof and keys into the circuit.
    2. Prepare the Key: If using VerifyingKeyVar, call .prepare() to create a PreparedVerifyingKeyVar.
    3. Verify: Call verify (which uses the prepared key internally) or verify_with_processed_vk (if you already have a PreparedVerifyingKeyVar) to obtain a Boolean variable representing the validity of the proof.
    // Assuming TestSNARKGadget is an instance of Groth16VerifierGadget
    // and you have allocated input_gadget, proof_gadget, and vk_gadget
    
    // Option 1: Using the standard verify method
    <TestSNARKGadget as SNARKGadget<...>>::verify(
        &vk_gadget, 
        &input_gadget, 
        &proof_gadget
    )?
    .enforce_equal(&Boolean::constant(true))
    .unwrap();
    
    // Option 2: Using the optimized verify_with_processed_vk method
    let pvk = TestSNARK::process_vk(&vk).unwrap();
    let pvk_gadget = <TestSNARKGadget as SNARKGadget<...>>::ProcessedVerifyingKeyVar::new_constant(
        ns!(cs, "alloc_pvk"), 
        pvk.clone()
    ).unwrap();
    
    <TestSNARKGadget as SNARKGadget<...>>::verify_with_processed_vk(
        &pvk_gadget, 
        &input_gadget, 
        &proof_gadget
    )?
    .enforce_equal(&Boolean::constant(true))
    .unwrap();
  6. Use LibsnarkReduction to map R1CS to QAP

    master

    The LibsnarkReduction struct implements the R1CSToQAP trait following the reduction method used in libsnark.

    Use instance_map_with_evaluation to compute the QAP instance. This method requires a ConstraintSystemRef and a target point t (the evaluation point). It returns a tuple containing:

    • a: Polynomial coefficients for $a(x)$
    • b: Polynomial coefficients for $b(x)$
    • c: Polynomial coefficients for $c(x)$
    • zt: The vanishing polynomial $Z_T(x)$ evaluated at t
    • qap_num_variables: The number of variables in the QAP
    • domain_size: The size of the evaluation domain used
  7. Prepare a VerifyingKey for efficient verification

    master

    To optimize the verification process, you should convert a standard VerifyingKey<E> into a PreparedVerifyingKey<E> using prepare_verifying_key. This precomputes certain pairings and negations (like alpha_g1_beta_g2 and negated gamma_g2 and delta_g2) required during the proof verification step.

    let pvk = prepare_verifying_key(&vk);
  8. Map R1CS witnesses from matrices

    master

    If you have the R1CS matrices and the full assignment separately, use witness_map_from_matrices from the R1CSToQAP trait.

    Parameters:

    • matrices: A slice of Matrix<F> representing the R1CS constraints.
    • num_inputs: Number of instance variables.
    • num_constraints: Number of constraints.
    • full_assignment: A slice containing both instance and witness assignments concatenated.
  9. Verify a Groth16 proof with pre-prepared inputs

    master

    For scenarios where the public inputs are known in advance or can be processed incrementally, use prepare_inputs followed by verify_proof_with_prepared_inputs. This allows you to compute the public input contribution to the verification equation (g_ic) once and reuse it, which is more efficient than recomputing it every time if the inputs are static.

    // 1. Prepare the public input contribution
    let prepared_inputs = Groth16::<E, QAP>::prepare_inputs(&pvk, &public_inputs)?;
    
    // 2. Verify using the prepared G1 element
    let is_valid = Groth16::<E, QAP>::verify_proof_with_prepared_inputs(&pvk, &proof, &prepared_inputs)?;
  10. Map R1CS witnesses to QAP witnesses

    master

    To convert a witness from R1CS to QAP, use the witness_map method provided by the R1CSToQAP trait.

    If you have a ConstraintSystemRef that already contains the assignments (the prover's state), you can call witness_map directly. It internally extracts the matrices and the full assignment (instance variables + witness variables) to perform the reduction.

  11. Evaluate a single constraint with evaluate_constraint

    master

    The evaluate_constraint function computes the inner product of a set of terms with a given assignment. This is used during the witness mapping process.

    Arguments:

    • terms: A slice of tuples (F, usize), where F is the coefficient and usize is the index in the assignment.
    • assignment: A slice of field elements representing the current variable assignments.

    Performance:

    • If the parallel feature is enabled, it uses rayon for multi-threaded execution on large term sets (length $\ge 100$).
    • Otherwise, it uses a sequential implementation optimized with chunking for CPU vectorization.