npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@nori-zk/proof-conversion-utils

v0.5.2

Published

WebAssembly utilities for converting zero-knowledge proofs between different formats, with a focus on targeting Mina Protocol's o1js framework.

Readme

@nori-zk/proof-conversion-utils

WebAssembly utilities for converting zero-knowledge proofs between different formats, with a focus on targeting Mina Protocol's o1js framework.

Installation

npm install @nori-zk/proof-conversion-utils

Overview

This package provides utilities to assist witness creation and alpha-beta pairing. As well as converting Groth16 zero-knowledge proofs from various sources (SnarkJS, SP1) into the format required by o1js for verification in Mina Protocol zkApps.

TypeScript API


Types

AffinePoint2d

A 2D affine point with x and y coordinates.

Each coordinate is a decimal string representing a large integer (BigInt in JS). For example, 254-bit integers when using the BN254 curve.

Used for G1 curve points in affine form (no z coordinate).

interface AffinePoint2d {
  x: string;  // String representation of x coordinate
  y: string;  // String representation of y coordinate
}

ComplexAffinePoint2d

A 2D affine point with complex coordinates (each coordinate has real and imaginary parts).

x = (x_c0, x_c1) and y = (y_c0, y_c1), where c0 is real and c1 is imaginary. Each component is a decimal string representing a large integer (BigInt in JS). For example, 254-bit integers when using the BN254 curve.

Used for G2 curve points in affine form (no z coordinate).

interface ComplexAffinePoint2d {
  x_c0: string;  // Real part of x coordinate
  x_c1: string;  // Imaginary part of x coordinate
  y_c0: string;  // Real part of y coordinate
  y_c1: string;  // Imaginary part of y coordinate
}

ProjectivePoint

Represents a projective point with x, y, z coordinates.

Each coordinate is a decimal string representing a large integer (BigInt in JS). For example, 254-bit integers when using the BN254 curve.

Used for G1 curve points in projective form as output by snarkjs.

export type ProjectivePoint = [string, string, string];

ComplexProjectivePoint

A projective point with complex coordinates.

Each coordinate has real (c0) and imaginary (c1) parts. Each component is a decimal string representing a large integer (BigInt in JS).

Used for G2 curve points in projective form as output by snarkjs.

export type ComplexProjectivePoint = [[string, string], [string, string], [string, string]];

Field12

A 12-element field value (Fq12) serialized as decimal strings. Used for pairing outputs like alpha_beta and w27 in verification keys.

Structure

Fq12 is built from a 'tower' of field extensions:

  • Fq: A single 254-bit integer (the base field)
  • Fq2: Two Fq values (real + imaginary)
  • Fq6: Three Fq2 values
  • Fq12: Two Fq6 values (g and h in our serialization)

So: Fq12 = 2 × Fq6 = 2 × 3 × Fq2 = 12 base field elements.

Naming Convention

{group}{pair}{component}:

  • group: g or h
  • pair: 0, 1, or 2 (which pair within the group)
  • component: 0 (real) or 1 (imaginary)
interface Field12 {
  g00: string;
  g01: string;
  g10: string;
  g11: string;
  g20: string;
  g21: string;
  h00: string;
  h01: string;
  h10: string;
  h11: string;
  h20: string;
  h21: string;
}

PairingInput

Input for computing a pairing operation.

A pairing combines a G1 point and a G2 point to produce a 12-element field value. In Groth16/PLONK verification keys, this is used to precompute e(alpha, beta).

  • alpha: G1 curve point (simple 2D coordinates)
  • beta: G2 curve point (complex 2D coordinates, each coordinate is a pair)
interface PairingInput {
  alpha: AffinePoint2d;
  beta: ComplexAffinePoint2d;
}

AuxWitness

Auxiliary witness for pairing verification.

Contains precomputed hints for efficient final exponentiation:

  • c: A 12-element field value
  • shift_power: A small integer (0, 1, or 2) for the shift factor
interface AuxWitness {
  c: Field12;
  shift_power: string;  // '0', '1', or '2'
}

O1jsProof

Groth16 proof in o1js format.

Contains the three proof curve points plus public inputs:

  • negA: Negated A point (G1)
  • B: B point (G2 - complex coordinates)
  • C: C point (G1)
  • pi1 through pi6: Public inputs (max 6 supported)
interface O1jsProof {
  negA: AffinePoint2d;  // Negated A point (G1)
  B: ComplexAffinePoint2d;  // B point (G2)
  C: AffinePoint2d;  // C point (G1)
  pi1?: string;  // Public input 1 (optional)
  pi2?: string;  // Public input 2 (optional)
  pi3?: string;  // Public input 3 (optional)
  pi4?: string;  // Public input 4 (optional)
  pi5?: string;  // Public input 5 (optional)
  pi6?: string;  // Public input 6 (optional)
}

O1jsVK

Groth16 verification key in o1js format.

Contains the verification key parameters needed for proof verification:

  • alpha: Alpha point from trusted setup (G1)
  • beta, gamma, delta: Curve points from the trusted setup (G2)
  • alpha_beta: Precomputed pairing e(alpha, beta) as a 12-element field value
  • w27: A 27th root of unity used for pairing optimizations
  • ic0 through ic6: Input commitment points for public input verification. ic0 is always present (the constant term). ic1-ic6 are optional based on how many public inputs the circuit has (max 6 supported).

The Groth16 verification equation uses: PI = ic0 + Σ(public_input[i] * ic[i+1])

interface O1jsVK {
  alpha: AffinePoint2d;
  beta: ComplexAffinePoint2d;
  gamma: ComplexAffinePoint2d;
  delta: ComplexAffinePoint2d;
  alpha_beta: Field12;  // Precomputed pairing e(α, β)
  w27: Field12;  // 27th root of unity for pairing optimizations
  ic0: AffinePoint2d;  // Constant term (always present)
  ic1?: AffinePoint2d;  // Optional IC points based on circuit
  ic2?: AffinePoint2d;
  ic3?: AffinePoint2d;
  ic4?: AffinePoint2d;
  ic5?: AffinePoint2d;
  ic6?: AffinePoint2d;
}

O1jsGroth16

Groth16 proof and verification key in o1js format.

Contains both the converted proof and verification key ready for verification in Mina using o1js.

interface O1jsGroth16 {
  proof: O1jsProof;
  vk: O1jsVK;
}

SnarkjsProof

Groth16 proof in snarkjs/circom format.

This is the input format produced by snarkjs when generating proofs. Points are in projective coordinates (with z component).

  • pi_a: A point (G1 projective)
  • pi_b: B point (G2 projective)
  • pi_c: C point (G1 projective)
interface SnarkjsProof {
  pi_a: [string, string, string];  // A point in G1 projective
  pi_b: [[string, string], [string, string], [string, string]];  // B point in G2 projective
  pi_c: [string, string, string];  // C point in G1 projective
}

SnarkjsVK

Groth16 verification key in snarkjs/circom format.

This is the input format produced by snarkjs when compiling circom circuits. Points are in projective coordinates (with z component).

  • nPublic: Number of public inputs in the circuit
  • vk_alpha_1: Alpha point (G1 projective)
  • vk_beta_2, vk_gamma_2, vk_delta_2: Setup points (G2 projective)
  • IC: Input commitment points, one per public input plus a constant term
interface SnarkjsVK {
  nPublic: number;
  vk_alpha_1: [string, string, string];
  vk_beta_2: [[string, string], [string, string], [string, string]];
  vk_gamma_2: [[string, string], [string, string], [string, string]];
  vk_delta_2: [[string, string], [string, string], [string, string]];
  IC: Array<[string, string, string]>;
}

Groth16Bn254Proof

Groth16 proof in SP1/gnark format. Mirrors sp1_prover::Groth16Bn254Proof.

export interface Groth16Bn254Proof {
    public_inputs: [string, string];
    encoded_proof: string;
    raw_proof: string;
    groth16_vkey_hash: number[];
}

PlonkBn254Proof

Plonk proof in SP1/gnark format. Mirrors sp1_prover::PlonkBn254Proof.

export interface PlonkBn254Proof {
    public_inputs: [string, string];
    encoded_proof: string;
    raw_proof: string;
    plonk_vkey_hash: number[];
}

SP1Proof

SP1 proof enum containing different proof types. Mirrors sp1_stark::SP1Proof.

export type SP1Proof = { Groth16: Groth16Bn254Proof } | { Plonk: PlonkBn254Proof };

SP1PublicValues

SP1 public values. Mirrors sp1_primitives::io::SP1PublicValues.

export interface SP1PublicValues {
    buffer: SP1Buffer;
}

#### `SP1ProofWithPublicValues`
SP1 proof with public values.
Mirrors `sp1_sdk::proof::SP1ProofWithPublicValues`.

```typescript
export interface SP1ProofWithPublicValues {
    proof: SP1Proof;
    public_values: SP1PublicValues;
    sp1_version: string;
    tee_proof: number[] | null;
}

Functions

compute_aux_witness

export function compute_aux_witness(input: Field12): AuxWitness;

Computes the auxiliary witness from a Miller loop output.

What This Does

Takes a 12-element field value (the result of a Miller loop pairing computation) and computes the auxiliary witness needed for efficient verification.

The Miller loop is the first step of pairing-based verification. Its output needs further processing (final exponentiation), which is expensive. The auxiliary witness provides precomputed hints that make this step efficient.

Input

A JS object matching Field12 structure (12 string fields: g00-g21, h00-h21).

Output

Return a JS object matching AuxWitness structure containing:

  • c: A 12-element field value
  • shift_power: "0", "1", or "2"

Error

Throws a JsError if the input is not a valid Miller loop output (fails internal assertion).

compute_pairing

export function compute_pairing(input: PairingInput): Field12;

Computes a pairing for a verification key.

What This Does

Takes two curve points (alpha and beta from the trusted setup) and computes their pairing using the Miller loop algorithm. The result is a 12-element field value that gets stored in the verification key.

This pairing e(alpha, beta) is constant for a given verification key, so it's precomputed once and reused for all proof verifications.

Input

A JS object matching PairingInput structure:

  • alpha: An AffinePoint2d with x and y fields
  • beta: A ComplexAffinePoint2d with x_c0, x_c1, y_c0, y_c1 fields

Output

Returns a JS object matching Field12 structure (12 string fields: g00-g21, h00-h21).

Errors

Throws a JS error if input parsing or coordinate conversion fails.

convert_snarkjs_groth16_to_o1js

export function convert_snarkjs_groth16_to_o1js(proof: SnarkjsProof, public_inputs: string[], vk: SnarkjsVK): O1jsGroth16;

Converts a snarkjs/circom Groth16 proof and verification key to o1js format.

This function takes Groth16 proofs generated by snarkjs (the JavaScript implementation of Groth16 commonly used with circom circuits) and converts them to o1js format for verification in Mina Protocol zkApps.

Conversion Details

Proof Conversion

  • The A point (pi_a) is negated for o1js compatibility. The o1js verification equation uses -A rather than A in the pairing check.
  • Points are converted from projective coordinates (with z component) to affine form.
  • The B point is a G2 point with complex coordinates (x_c0, x_c1, y_c0, y_c1).
  • The C point is a G1 point with simple coordinates (x, y).

Verification Key Conversion

  • All curve points are converted from projective to affine form.
  • The alpha_beta pairing e(α, β) is computed using arkworks multi_miller_loop. This is a constant for each VK and is precomputed to save verification time.
  • A hardcoded w27 (27th root of unity) is added for pairing optimizations. See https://eprint.iacr.org/2024/640 for the optimization technique.
  • IC (input commitment) points are mapped to ic0-ic6 fields.

Validation

  • The nPublic field in the VK must match the number of public inputs provided.
  • The IC array length must equal nPublic + 1 (ic0 is the constant term).

Input Format

  • proof: snarkjs proof JSON object with:

    • pi_a: [x, y, z] - A point in G1 projective coordinates
    • pi_b: [[x_c0, x_c1], [y_c0, y_c1], [z_c0, z_c1]] - B point in G2 projective
    • pi_c: [x, y, z] - C point in G1 projective coordinates
  • public_inputs: Array of public input strings as decimal numbers, e.g., ["123", "456"]. Maximum 6 public inputs are supported.

  • vk: snarkjs verification key JSON object with:

    • nPublic: Number of public inputs
    • vk_alpha_1: Alpha point (G1 projective)
    • vk_beta_2: Beta point (G2 projective)
    • vk_gamma_2: Gamma point (G2 projective)
    • vk_delta_2: Delta point (G2 projective)
    • IC: Array of IC points (G1 projective), length = nPublic + 1

Output Format

Returns a JS object matching O1jsGroth16 containing:

  • proof: o1js-formatted proof with:

    • negA: Negated A point {x, y} as decimal strings
    • B: B point {x_c0, x_c1, y_c0, y_c1} as decimal strings
    • C: C point {x, y} as decimal strings
    • pi1 through pi6: Public inputs (only present if provided)
  • vk: o1js-formatted verification key with:

    • alpha, beta, gamma, delta: Curve points
    • alpha_beta: Precomputed pairing as 12-element Fq12 field
    • w27: 27th root of unity as 12-element Fq12 field
    • ic0 through ic6: Input commitment points (only present if in VK)

Errors

Throws a JsError error if:

  • Input JSON parsing fails (invalid structure or types)
  • VK validation fails (nPublic doesn't match public inputs count, wrong IC length)
  • Point coordinate parsing fails (invalid field element strings)
  • More than 6 public inputs are provided

convert_sp1_groth16_to_o1js

export function convert_sp1_groth16_to_o1js(sp1_proof: SP1ProofWithPublicValues): O1jsGroth16;

Converts an SP1 Groth16 proof to o1js format.

This function takes Groth16 proofs generated by SP1 (Succinct's zkVM) and converts them to o1js format for verification in Mina Protocol zkApps. SP1 uses gnark's Groth16 implementation internally, which produces proofs in a compressed format that must be decompressed before conversion.

Conversion Details

Proof Extraction & Decompression

  • The encoded_proof field contains hex-encoded gnark proof bytes.
  • The first 4 bytes of the proof are a vkey hash prefix (skipped during parsing).
  • gnark uses a compressed point format that differs from arkworks. This function decompresses G1 and G2 points using endianness conversion and flag translation.
  • The decompression follows the gnark → arkworks conversion from sp1-sui.

Proof Conversion

  • The A point is negated for o1js compatibility. The o1js verification equation uses -A rather than A in the pairing check.
  • SP1 Groth16 proofs have exactly 2 public inputs (vkey_hash and public_values_hash).

Verification Key

  • All SP1 v5.0.0 Groth16 proofs use the same verification key. This VK is embedded in the library (GROTH16_VK_5_0_0_BYTES) and loaded automatically.
  • The VK is decompressed from gnark format to arkworks format.
  • The alpha_beta pairing e(α, β) is computed and included in the output.
  • The hardcoded w27 (27th root of unity) is added for pairing optimizations.

Input Format

  • sp1_proof: SP1ProofWithPublicValues JSON shim object representation
  • FIXME write an example here!

Output Format

Returns a JS object O1jsGroth16 containing:

  • proof: o1js-formatted proof with:

    • negA: Negated A point {x, y} as decimal strings
    • B: B point {x_c0, x_c1, y_c0, y_c1} as decimal strings
    • C: C point {x, y} as decimal strings
    • pi1: First public input (vkey_hash)
    • pi2: Second public input (public_values_hash)
  • vk: o1js-formatted SP1 v5.0.0 verification key with:

    • alpha, beta, gamma, delta: Curve points
    • alpha_beta: Precomputed pairing as 12-element Fq12 field
    • w27: 27th root of unity as 12-element Fq12 field
    • ic0, ic1, ic2: Input commitment points (SP1 VK has 3 IC points)

Errors

Throws a JsError error if:

  • Input JSON parsing fails (invalid structure or types)
  • Proof is not the Groth16 variant (e.g., it's a PLONK proof)
  • Proof is empty (mock proof - not supported)
  • Hex decoding of encoded_proof fails
  • gnark point decompression fails (invalid curve points)

Usage Examples

Converting SnarkJS Proof

import { convert_snarkjs_groth16_to_o1js } from '@nori-zk/proof-conversion-utils';
import snarkjsProof from './proof.json';
import snarkjsVK from './verification_key.json';

const publicInputs = ['12345', '67890'];

const { proof, vk } = convert_snarkjs_groth16_to_o1js(
  snarkjsProof,
  publicInputs,
  snarkjsVK
);

// Use proof and vk with o1js for verification in Mina

Converting SP1 Proof

import { convert_sp1_groth16_to_o1js } from '@nori-zk/proof-conversion-utils';
import sp1Proof from './sp1_proof.json';

const { proof, vk } = convert_sp1_groth16_to_o1js(sp1Proof);

// Use proof and vk with o1js for verification in Mina

Computing Pairing

import { compute_pairing } from '@nori-zk/proof-conversion-utils';

const alphaBeta = compute_pairing({
  alpha: {
    x: '12369698276624038106972479882730964985390333465481074863680349672529458504727',
    y: '15615049479232918185966644204891621024197935236528708875381357850359187990605'
  },
  beta: {
    x_c0: '1903903027629957495668852277947233956036752695749808956450499753161040073874',
    x_c1: '19516214232409959981032970092985844340835031525223058295881548971699867691648',
    y_c0: '19307974034844496356197776793106808222110218706117190747312969862440532637662',
    y_c1: '13697410665674063166131807846290149764118701671708810697019074013384033689104'
  }
});

Supported Formats

  • SnarkJS: Groth16 proofs from snarkjs/circom circuits
  • SP1: Groth16 proofs from SP1 v5.0.0 zkVM
  • o1js: Target format for Mina Protocol zkApps

Technical Details

  • Built with Rust and compiled to WebAssembly for high performance
  • Uses the arkworks cryptography library for BN254 curve operations
  • All field elements are represented as strings for JavaScript compatibility
  • Supports BN254 elliptic curve pairing

License

Apache-2.0