Zero-Knowledge circuits for Orbinum privacy blockchain using Circom and Groth16.
npm install @orbinum/circuitsThis installs pre-compiled circuit artifacts ready to use. See npm package documentation.
git clone https://github.com/orbinum/circuits
cd circuits
npm run build-allBuild everything from scratch with one command:
npm run build-allThis automatically:
- Installs dependencies
- Compiles circuits (disclosure.circom β R1CS + WASM)
- Downloads Powers of Tau (72MB, one-time)
- Generates cryptographic keys (proving + verifying keys)
- Converts to compatible formats
- Generates
manifest.jsonwith SHA-256 hashes for artifacts (when usingnpm run build-all:manifest)
npm run manifestThis creates manifest.json at repo root with:
- package version metadata
- active/supported version per circuit
- SHA-256 + size for
.wasm,.zkey,.ark(if available) vk_hashderived fromverification_key_<circuit>.json
Output:
build/disclosure_js/disclosure.wasm(2.1MB) - Witness calculatorkeys/disclosure_pk.zkey(689KB) - Proving keybuild/verification_key_disclosure.json(3.4KB) - Verifying key
The circuits can be used in Rust/Substrate projects in two ways:
Download the pre-built .ark file from releases. This is a serialized arkworks ProvingKey that loads 2-3x faster than parsing .zkey files.
Setup:
[dependencies]
ark-bn254 = "0.5.0"
ark-groth16 = "0.5.0"
ark-serialize = "0.5.0"Usage:
use ark_bn254::Bn254;
use ark_groth16::{Groth16, ProvingKey};
use ark_serialize::CanonicalDeserialize;
use std::fs::File;
// Load .ark file (fast)
let mut ark_file = File::open("keys/disclosure_pk.ark")?;
let proving_key = ProvingKey::<Bn254>::deserialize_compressed(&mut ark_file)?;
// Generate proof
let proof = Groth16::<Bn254>::prove(&proving_key, circuit, &mut rng)?;The .zkey files work directly with the ark-circom library - no conversion needed.
Setup:
[dependencies]
ark-circom = "0.5.0"
ark-bn254 = "0.5.0"
ark-groth16 = "0.5.0"Usage:
use ark_circom::{read_zkey, CircomConfig, CircomBuilder};
use ark_bn254::Bn254;
use ark_groth16::Groth16;
use std::fs::File;
// Read .zkey file directly
let mut zkey_file = File::open("keys/disclosure_pk.zkey")?;
let (proving_key, matrices) = read_zkey(&mut zkey_file)?;
// Configure circuit with WASM
let cfg = CircomConfig::<Bn254>::new(
"build/disclosure_js/disclosure.wasm",
"build/disclosure.r1cs"
)?;
// Build circuit with inputs
let mut builder = CircomBuilder::new(cfg);
builder.push_input("note_value", 1000);
builder.push_input("note_asset_id", 42);
// ... add more inputs
// Generate proof
let circom = builder.build()?;
let proof = Groth16::<Bn254>::prove(&proving_key, circom, &mut rng)?;If you need to generate the .ark file yourself:
# Using the Rust script
cargo +nightly -Zscript scripts/build/convert-to-ark.rs \
keys/disclosure_pk.zkey \
keys/disclosure_pk.ark
# Or via npm
npm run convert:disclosureGet pre-built circuits from GitHub Releases:
# Download latest release
wget https://github.com/orb-labs/circuits/releases/latest/download/disclosure-circuit-v*.tar.gz
# Extract files
tar -xzf disclosure-circuit-v*.tar.gz
# Use in your Rust project
cp keys/disclosure_pk.zkey /path/to/your/rust/project/
cp build/disclosure_js/disclosure.wasm /path/to/your/rust/project/npm testTest Suites:
disclosure.test.ts- Selective disclosure circuittransfer.test.ts- Private transfer logicunshield.test.ts- Multi-asset supportmerkle_tree.test.ts- Merkle proof verificationnote.test.ts- Note commitment schemesposeidon_*.test.ts- Hash function compatibility
Expected: ~86 tests passing in 7 seconds
npm test -- --grep "disclosure"Generate test inputs first:
npm run gen-input:disclosureThis creates 4 test scenarios:
reveal_nothing- Full privacyreveal_value_only- Amount visiblereveal_value_and_asset- Amount + asset type visiblereveal_all- Complete disclosure
# Disclosure circuit
npm run bench:disclosure
# Transfer circuit (coming soon)
npm run bench:transfer
# All circuits
npm run benchMetrics measured:
- Witness generation time
- Proof generation time
- Proof verification time
- Memory usage
- Throughput (ops/sec)
Results saved to: build/benchmark_results_*.json
π Benchmarking Proof Generation (10 iterations)...
Proof Generation:
Average: 101.29 ms
Min: 97.62 ms
Max: 109.43 ms
Throughput: 9.87 ops/sec
Complete automated workflows from compilation to proof generation.
npm run e2e:disclosureWhat it does:
- Compiles circuit
- Sets up keys
- Generates test inputs (4 scenarios)
- Creates proofs for all scenarios
- Verifies all proofs
Generated artifacts:
- 4 input files:
build/disclosure_input_*.json - 4 proof files:
build/proof_disclosure_*.json - 4 public signals:
build/public_disclosure_*.json
npm run e2e:transfer# Remove all generated files
rm -rf keys/ build/ node_modules/
# Rebuild everything
npm run build-all# Step 1: Compile circuit
npm run compile:disclosure
# Step 2: Generate keys (requires compilation)
npm run setup:disclosure
# Step 3: Convert to compatible format (optional)
npm run convert:discord
# Or run all steps together
npm run full-build:disclosureWhy is this needed?
The fp-encrypted-memo primitive can use WASM to calculate the complete circuit witness (~740 wires) without reimplementing all Circom logic in Rust. This ensures:
- β Accuracy: Executes the exact circuit logic
- β Maintainability: Updates automatically when circuit is recompiled
- β Consistency: Avoids bugs from code duplication
- β Completeness: Generates all intermediate wires needed
From circuits/circuits/ directory:
# Compile disclosure.circom to WASM
circom disclosure.circom --wasm --output ../build/Generated file:
build/disclosure_js/disclosure.wasm(~2.1MB)
Usage in Rust:
// With feature flag: wasm-witness
let wasm_bytes = std::fs::read("circuits/build/disclosure_js/disclosure.wasm")?;
let witness = calculate_witness_wasm(&wasm_bytes, &inputs, &signals)?;Note: WASM is also generated automatically with npm run build-all.
# Disclosure circuit (4 scenarios)
npm run gen-input:disclosure
# Transfer circuit
npm run gen-input:transfer# Disclosure proofs
npm run prove:disclosure
# Transfer proofs
npm run prove:transferPurpose: Selective disclosure of encrypted memo fields
Statistics:
- Constraints: 1,584
- Private inputs: 8
- Public inputs: 4
- Wires: 1,586
Features:
- Commitment verification
- Selective field revelation
- Viewing key authentication
- Zero-knowledge privacy
circuits/
βββ circuits/ # Circom source files
β βββ disclosure.circom
βββ build/ # Compiled artifacts
β βββ disclosure_js/
β β βββ disclosure.wasm
β βββ verification_key_*.json
βββ keys/ # Cryptographic keys
β βββ disclosure_pk.zkey
β βββ disclosure_pk.ark
βββ test/ # Test suites
βββ benches/ # Performance benchmarks
βββ scripts/ # Build and generation scripts
β βββ build/ # Compilation scripts
β βββ generators/ # Input/proof generators
β βββ e2e-*.ts # End-to-end workflows
βββ package.json
- Node.js >= 18
- npm >= 9
- circom >= 2.2.0
- snarkjs >= 0.7.0
All requirements are checked automatically by build scripts.
Run input generator first:
npm run gen-input:disclosureCheck internet connection. The script will retry with fallback URLs automatically.
Ensure circom is installed:
circom --version # Should be >= 2.2.0rm -rf keys/ build/ node_modules/
npm run build-allDevelopment Machine (M2 MacBook Air):
- Full build: ~25 seconds (including PoT download)
- Subsequent builds: ~10 seconds
- Proof generation: ~100ms
- Proof verification: ~5ms
Note: This project is currently not accepting external contributions. The repository is open for transparency and reference purposes.
Apache 2.0 / GPL3 - See LICENSE files