Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
691b943
feat: implement snarkjs proof compression and validation in WASM
nol4lej Feb 16, 2026
d872903
feat: refactor proof generation to use decimal format and update tests
nol4lej Feb 16, 2026
9464c18
feat: update WASM exports to include proof compression function
nol4lej Feb 16, 2026
a6fe0e1
feat: add README.md for Groth16 proof generator with usage examples a…
nol4lej Feb 16, 2026
ffbf1f6
feat: add package.json.template for Groth16 proof generator configura…
nol4lej Feb 16, 2026
80dbacb
feat: update witness formats documentation to clarify decimal format …
nol4lej Feb 16, 2026
102e590
feat: update usage documentation for proof generation and rename lega…
nol4lej Feb 16, 2026
bac3c08
feat: remove outdated release process documentation
nol4lej Feb 16, 2026
96f8a37
feat: update installation guide for Groth16 proofs with version and W…
nol4lej Feb 16, 2026
9465920
feat: enhance release workflow to include npm package configuration a…
nol4lej Feb 16, 2026
cf193aa
feat: remove pre-release hook for WASM build from release configuration
nol4lej Feb 16, 2026
a67c6e2
feat: update README for WASM npm package integration and decimal-only…
nol4lej Feb 16, 2026
c8998e9
feat: enhance WASM build process to configure npm package and include…
nol4lej Feb 16, 2026
9da25de
feat: update CHANGELOG for decimal-only WASM proof generation and new…
nol4lej Feb 16, 2026
974e2bd
feat: update package version to 2.0.0 and add npm package metadata fo…
nol4lej Feb 16, 2026
c2a9b21
feat: update byte order in proof generation to little-endian and ensu…
nol4lej Feb 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 0 additions & 13 deletions .cargo/release.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,5 @@ tag-message = "Release {{version}}"
tag-name = "v{{version}}"
# IMPORTANT: Automatically update CHANGELOG.md
changelog-update = true
# Build WASM before release (as a pre-release hook)
pre-release-hook = [
{ cmd = "wasm-pack", args = [
"build",
"--target",
"web",
"--out-dir",
"./pkg",
"--release",
"--features",
"wasm",
] },
]
# Only allow releases from main branch
allow-branch = ["main"]
33 changes: 33 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ on:
paths:
- "Cargo.toml"
- "src/**"
- "npm/**"
- ".github/workflows/release.yml"

permissions:
Expand Down Expand Up @@ -80,6 +81,23 @@ jobs:
if: steps.check_tag.outputs.exists == 'false'
run: wasm-pack build --target web --out-dir ./pkg --release --features wasm

- name: Configure npm package.json
if: steps.check_tag.outputs.exists == 'false'
run: |
cd pkg
# Generate package.json from template (same approach as circuits)
node -e "
const fs = require('fs');
const template = fs.readFileSync('../npm/package.json.template', 'utf8');
const rendered = template.replace(/__VERSION__/g, '${{ steps.version.outputs.version }}');
JSON.parse(rendered);
fs.writeFileSync('package.json', rendered);
"
# Copiar README específico para npm
cp ../npm/README.md ./README.md
echo "📦 Configured package.json:"
cat package.json

- name: Create WASM package artifact
if: steps.check_tag.outputs.exists == 'false'
run: |
Expand All @@ -105,3 +123,18 @@ jobs:
run: cargo publish --token ${{ secrets.CARGO_REGISTRY_TOKEN }}
env:
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}

- name: Setup Node.js for npm publish
if: steps.check_tag.outputs.exists == 'false'
uses: actions/setup-node@v4
with:
node-version: '22'
registry-url: 'https://registry.npmjs.org'

- name: Publish to npm
if: steps.check_tag.outputs.exists == 'false'
run: |
cd pkg
npm publish
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,24 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added
- `compress_snarkjs_proof_wasm()` WASM API for snarkjs proof (`pi_a`, `pi_b`, `pi_c`) to arkworks canonical compressed bytes conversion.
- Internal `src/wasm/snarkjs_proof.rs` module to separate snarkjs parsing/validation/compression responsibilities.
- `npm/package.json.template` as source of truth for npm package metadata (rendered with release version in CI/local builds).

### Changed
- **BREAKING**: WASM proof generation is now decimal-only via `generate_proof_from_decimal_wasm()`.
- Documentation updated to reflect decimal-only WASM proof flow and snarkjs interoperability path.
- Release workflow now generates `pkg/package.json` from template (circuits-style), builds release asset (`orb-groth16-proof.tar.gz`), and publishes the rendered `pkg` package to npm.
- Release workflow trigger paths now include `npm/**` to ensure packaging metadata/template changes run through release automation.
- `Makefile` (`build-wasm`, `build-wasm-dev`) now renders `pkg/package.json` from template using `Cargo.toml` version for local parity with CI.
- `cargo-release` responsibility narrowed to version/changelog/tag preparation; WASM build is handled in CI release job to avoid duplicate builds.

### Removed
- **BREAKING**: Removed legacy WASM API `generate_proof_wasm()` (hex little-endian witness input).

## [1.0.0](https://github.com/orbinum/groth16-proofs/releases/tag/v1.0.0) - 2026-02-12

### Added
Expand Down
6 changes: 5 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "groth16-proofs"
version = "1.1.0"
version = "2.0.0"
edition = "2021"
license = "Apache-2.0 OR GPL-3.0-or-later"
description = "High-performance Groth16 proof generator using arkworks for Orbinum privacy protocol"
Expand All @@ -12,6 +12,10 @@ keywords = ["zk-snark", "groth16", "proof-generation", "arkworks", "privacy"]
[lib]
crate-type = ["cdylib", "rlib"]

# npm package metadata (consumed by wasm-pack)
[package.metadata.wasm-pack.profile.release]
wasm-opt = true

[[bin]]
name = "generate-proof-from-witness"
path = "src/bin/generate-proof-from-witness.rs"
Expand Down
28 changes: 26 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,37 @@ build-wasm: ## Build WASM module (release)
@echo "$(BLUE)Building WASM module...$(NC)"
@command -v wasm-pack >/dev/null 2>&1 || { echo "$(YELLOW)Installing wasm-pack...$(NC)"; curl https://rustwasm.org/wasm-pack/installer/init.sh -sSf | sh; }
wasm-pack build --target web --out-dir ./pkg --release --features wasm
@echo "$(GREEN)✓ WASM: ./pkg/orbinum_groth16_proofs.wasm$(NC)"
@echo "$(BLUE)Configuring npm package...$(NC)"
@cd pkg && node -e "\
const fs = require('fs');\
const cargoToml = fs.readFileSync('../Cargo.toml', 'utf8');\
const versionMatch = cargoToml.match(/^version\s*=\s*\"(.+)\"/m);\
if (!versionMatch) throw new Error('Could not extract version from Cargo.toml');\
const template = fs.readFileSync('../npm/package.json.template', 'utf8');\
const rendered = template.replace(/__VERSION__/g, versionMatch[1]);\
JSON.parse(rendered);\
fs.writeFileSync('package.json', rendered);\
"
@cp npm/README.md pkg/README.md
@echo "$(GREEN)✓ WASM: ./pkg/@orbinum/groth16-proofs$(NC)"

build-wasm-dev: ## Build WASM module (dev/unoptimized)
@echo "$(BLUE)Building WASM module (dev)...$(NC)"
@command -v wasm-pack >/dev/null 2>&1 || { echo "$(YELLOW)Installing wasm-pack...$(NC)"; curl https://rustwasm.org/wasm-pack/installer/init.sh -sSf | sh; }
wasm-pack build --target web --out-dir ./pkg --dev --features wasm
@echo "$(GREEN)✓ WASM (dev): ./pkg/orbinum_groth16_proofs.wasm$(NC)"
@echo "$(BLUE)Configuring npm package...$(NC)"
@cd pkg && node -e "\
const fs = require('fs');\
const cargoToml = fs.readFileSync('../Cargo.toml', 'utf8');\
const versionMatch = cargoToml.match(/^version\s*=\s*\"(.+)\"/m);\
if (!versionMatch) throw new Error('Could not extract version from Cargo.toml');\
const template = fs.readFileSync('../npm/package.json.template', 'utf8');\
const rendered = template.replace(/__VERSION__/g, versionMatch[1]);\
JSON.parse(rendered);\
fs.writeFileSync('package.json', rendered);\
"
@cp npm/README.md pkg/README.md
@echo "$(GREEN)✓ WASM (dev): ./pkg/@orbinum/groth16-proofs$(NC)"

# Build everything
build-all: build build-wasm ## Build both native and WASM
Expand Down
57 changes: 39 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,47 +2,62 @@

> High-performance Groth16 proof generator using arkworks for Orbinum privacy protocol

[![npm version](https://img.shields.io/npm/v/@orbinum/groth16-proofs.svg)](https://www.npmjs.com/package/@orbinum/groth16-proofs)
[![Crates.io](https://img.shields.io/crates/v/groth16-proofs.svg)](https://crates.io/crates/groth16-proofs)
[![License](https://img.shields.io/badge/license-Apache--2.0%20OR%20GPL--3.0-blue)](./LICENSE-APACHE2)

Efficient **Groth16 zero-knowledge proof generator** for Orbinum's privacy protocol. Compiles to both native Rust and WebAssembly for maximum flexibility.

## Quick Start
## 🚀 Quick Start

### Install

**Rust**:
**npm/yarn/pnpm** (WASM for JavaScript/TypeScript):
```bash
npm install @orbinum/groth16-proofs
```

**Rust** (Native binary):
```toml
[dependencies]
groth16-proofs = "0.1"
groth16-proofs = "2.0"
```

### Use

**Rust**:
```rust
use orbinum_groth16_proofs::generate_proof_from_witness;

let proof = generate_proof_from_witness(&witness, "proving_key.ark")?;
```

**JavaScript (Browser/Node.js)** - Direct from snarkjs:
**JavaScript/TypeScript**:
```typescript
import { generate_proof_from_decimal_wasm } from './wasm/groth16_proofs.js';
import * as groth16 from '@orbinum/groth16-proofs';
import * as snarkjs from 'snarkjs';

// Initialize WASM
await groth16.default();
groth16.init_panic_hook();

// Calculate witness with snarkjs
const witnessArray = await snarkjs.wtns.exportJson('witness.wtns');

// Generate proof (no conversion needed!)
const result = generate_proof_from_decimal_wasm(
const result = groth16.generate_proof_from_decimal_wasm(
5, // number of public signals
JSON.stringify(witnessArray), // direct from snarkjs
provingKeyBytes
);

const { proof, publicSignals } = JSON.parse(result);
```

📖 **Full guides**: See [Installation](./docs/installation.md) and [Usage](./docs/usage.md)
**Rust**:
```rust
use groth16_proofs::generate_proof_from_witness;

let proof = generate_proof_from_witness(&witness, "proving_key.ark")?;
```

📖 **Full guides**:
- [Installation](./docs/installation.md)
- [Usage](./docs/usage.md)
- [Release Process](./docs/release.md)

## What Is This?

Expand All @@ -52,7 +67,11 @@ This crate generates **128-byte compressed Groth16 proofs** from witness data us
- **Curves**: BN254 (Ethereum-compatible)
- **Targets**: Native (Rust) + WebAssembly
- **Circuits**: Unshield, Transfer, Disclosure
- **Formats**: Decimal (snarkjs native) or Hex little-endian
- **WASM Input Format**: Decimal witness (snarkjs native)

For interoperability with snarkjs-generated proofs, the WASM API also exposes
`compress_snarkjs_proof_wasm()` to convert `pi_a/pi_b/pi_c` JSON into arkworks
canonical compressed proof bytes (`0x...`, 128 bytes).

## Architecture

Expand Down Expand Up @@ -89,14 +108,15 @@ This crate generates **128-byte compressed Groth16 proofs** from witness data us
| **proof.rs** | `src/` | Core Groth16 generation using arkworks |
| **circuit.rs** | `src/` | Circuit wrapper implementing ConstraintSynthesizer |
| **utils.rs** | `src/` | Format conversions (decimal ↔ hex ↔ field elements) |
| **wasm.rs** | `src/` | WASM FFI bindings with JSON I/O |
| **wasm.rs** | `src/` | WASM FFI bindings and public API re-exports |
| **wasm/snarkjs_proof.rs** | `src/wasm/` | snarkjs proof parsing/validation and compression |
| **binary** | `src/bin/` | CLI tool for Node.js integration |

## Features

✅ **Multiple Targets**: Native + WASM
✅ **Fast**: 5-8 second proof generation
✅ **Multiple Formats**: Decimal (snarkjs native) or Hex LE
✅ **WASM Decimal-Only API**: Direct snarkjs witness input
✅ **Type-Safe**: Memory-safe cryptography
✅ **Well-Tested**: 21+ tests included
✅ **Automated Release**: CI/CD pipeline ready
Expand All @@ -120,7 +140,7 @@ See [Makefile](./Makefile) for all available targets.

- [**Installation Guide**](./docs/installation.md) - Setup for Rust and JavaScript
- [**Usage Guide**](./docs/usage.md) - Complete API reference with examples
- [**Witness Formats**](./docs/witness-formats.md) - Decimal vs Hex LE formats explained
- [**Witness Formats**](./docs/witness-formats.md) - Decimal witness flow and format notes
- [**Release Process**](./docs/release.md) - How releases are managed

## Performance
Expand All @@ -140,6 +160,7 @@ See [Makefile](./Makefile) for all available targets.
This crate is published to both registries:

- **Rust**: [crates.io/crates/groth16-proofs](https://crates.io/crates/groth16-proofs)
- **npm**: [npmjs.com/package/@orbinum/groth16-proofs](https://www.npmjs.com/package/@orbinum/groth16-proofs)

## License

Expand Down
24 changes: 15 additions & 9 deletions docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,35 +16,41 @@ Add to your `Cargo.toml`:

```toml
[dependencies]
groth16-proofs = "0.1"
groth16-proofs = "2.0"
```

Then import in your code:

```rust
use orbinum_groth16_proofs::generate_proof_from_witness;
use groth16_proofs::generate_proof_from_witness;

let proof = generate_proof_from_witness(&witness, "proving_key.ark")?;
```

### As a WASM Module

**Note**: This library is not published to NPM. To use WASM, download the precompiled binaries from [GitHub Releases](https://github.com/orbinum/groth16-proofs/releases).
Install from npm:

```bash
npm install @orbinum/groth16-proofs
```

You can also download precompiled binaries from [GitHub Releases](https://github.com/orbinum/groth16-proofs/releases).

1. Download `orb-groth16-proof.tar.gz` from the latest release
2. Extract to your project:
1. Download `orb-groth16-proof.tar.gz` from the latest release (optional)
2. Extract to your project (optional):
```bash
tar -xzf orb-groth16-proof.tar.gz -C ./wasm
```

3. Import in TypeScript/JavaScript:

```typescript
import { generate_proof_wasm } from './wasm/groth16_proofs.js';
import { generate_proof_from_decimal_wasm } from './wasm/groth16_proofs.js';

// numPublicSignals depends on your circuit (check your circuit definition)
const numPublicSignals = 5;
const result = generate_proof_wasm(numPublicSignals, witnessJson, provingKeyBytes);
const result = generate_proof_from_decimal_wasm(numPublicSignals, witnessJson, provingKeyBytes);
```

### Development Installation
Expand Down Expand Up @@ -140,8 +146,8 @@ let proof = generate_proof_from_witness(&witness, "key.ark")?;

```typescript
// WASM
import { generate_proof_wasm } from './wasm/groth16_proofs.js';
const result = generate_proof_wasm(numPublicSignals, witnessJson, keyBytes);
import { generate_proof_from_decimal_wasm } from './wasm/groth16_proofs.js';
const result = generate_proof_from_decimal_wasm(numPublicSignals, witnessJson, keyBytes);
```

## Configuration
Expand Down
Loading