lambdaworks-groth16-ts
Version:
TypeScript bindings for LambdaWorks Groth16 SNARK prover
362 lines (241 loc) • 9.51 kB
Markdown
# lambdaworks-groth16-ts
# LambdaWorks Groth16 TypeScript Package
A high-performance TypeScript wrapper for LambdaWorks Groth16 SNARK prover, compiled to WebAssembly for browser and Node.js environments.
## Features
- **Fast Groth16 Implementation**: Built on LambdaWorks' optimized Rust implementation
- **WebAssembly Performance**: Near-native performance in browsers and Node.js
- **TypeScript Support**: Full type safety and excellent developer experience
- **Cross-Platform**: Works in browsers, Node.js, and React Native
- **Circom Compatible**: Direct integration with Circom circuit compiler
- **Production Ready**: Memory-safe Rust implementation with comprehensive testing
## Installation
```bash
npm install lambdaworks-groth16-ts
```
## Quick Start
```typescript
import LambdaWorksGroth16 from 'lambdaworks-groth16-ts';
async function example() {
// Initialize the library
const groth16 = await LambdaWorksGroth16.init();
// Load circuit from Circom
const r1csData = await fetch('./circuit.r1cs').then(r => r.arrayBuffer());
const wasmData = await fetch('./circuit.wasm').then(r => r.arrayBuffer());
const circuit = await groth16.circuitProcessor.loadFromCircom(
new Uint8Array(r1csData),
new Uint8Array(wasmData)
);
// Generate trusted setup (for testing - use ceremony setup in production)
const setup = groth16.setupManager.generateUnsafeSetup(circuit);
// Generate proof
const inputs = { x: "123", y: "456" };
const proof = await groth16.prover.proveWithInputs(circuit, setup.provingKey, inputs);
// Verify proof
const witness = groth16.circuitProcessor.computeWitness(circuit, inputs);
const isValid = groth16.verifier.verify(setup.verifyingKey, witness.publicInputs, proof);
console.log('Proof valid:', isValid);
}
```
## API Reference
### LambdaWorksGroth16
Main class providing access to all Groth16 functionality.
#### `static async init(wasmPath?: string): Promise<LambdaWorksGroth16>`
Initialize the library. Automatically detects browser/Node.js environment.
- `wasmPath`: Optional custom path to WASM file
#### Properties
- `prover: Groth16Prover` - Proof generation
- `verifier: Groth16Verifier` - Proof verification
- `setupManager: TrustedSetupManager` - Trusted setup handling
- `fieldOps: FieldOperations` - Field arithmetic operations
- `circuitProcessor: CircuitProcessor` - Circuit loading and witness computation
### CircuitProcessor
Handle circuit loading and witness computation.
#### `loadFromCircom(r1cs: Uint8Array, wasm: Uint8Array): Promise<Circuit>`
Load a circuit compiled with Circom.
#### `computeWitness(circuit: Circuit, inputs: Record<string, string>): Witness`
Compute witness for given circuit inputs.
#### `validateWitness(circuit: Circuit, witness: Witness): boolean`
Validate that witness satisfies circuit constraints.
### TrustedSetupManager
Manage trusted setup parameters.
#### `generateUnsafeSetup(circuit: Circuit): TrustedSetup`
⚠️ **WARNING**: Only for testing! Generate unsafe trusted setup.
#### `loadSetup(powersOfTau: Uint8Array, circuitSetup: Uint8Array): Promise<TrustedSetup>`
Load trusted setup from ceremony files.
#### `exportVerifyingKey(setup: TrustedSetup): string`
Export verifying key for on-chain verification.
### Groth16Prover
Generate Groth16 proofs.
#### `prove(circuit: Circuit, provingKey: ProvingKey, witness: Witness): Promise<Proof>`
Generate proof from circuit, proving key, and witness.
#### `proveWithInputs(circuit: Circuit, provingKey: ProvingKey, inputs: Record<string, string>): Promise<Proof>`
Generate proof directly from inputs (computes witness automatically).
#### `exportProof(proof: Proof, format: 'json' | 'solidity' | 'bytes'): string | Uint8Array`
Export proof in different formats for various use cases.
### Groth16Verifier
Verify Groth16 proofs.
#### `verify(verifyingKey: VerifyingKey, publicInputs: FieldElement[], proof: Proof): boolean`
Verify a single proof.
#### `batchVerify(verifyingKey: VerifyingKey, proofData: ProofData[]): boolean[]`
Efficiently verify multiple proofs.
### FieldOperations
Low-level field arithmetic operations.
#### `fromHex(hex: string): FieldElement`
Create field element from hex string.
#### `add(a: FieldElement, b: FieldElement): FieldElement`
Add two field elements.
#### `multiply(a: FieldElement, b: FieldElement): FieldElement`
Multiply two field elements.
## Building from Source
### Prerequisites
- Rust 1.70+
- Node.js 18+
- wasm-pack
### Build Steps
```bash
# Clone repository
git clone https://github.com/your-org/lambdaworks-groth16-ts
cd lambdaworks-groth16-ts
# Install dependencies
npm install
# Build WASM module
npm run build:wasm
# Build TypeScript
npm run build:ts
# Run tests
npm test
```
### Project Structure
```
├── src/ # TypeScript source
│ ├── index.ts # Main exports
│ ├── types.ts # Type definitions
│ ├── prover.ts # Prover implementation
│ ├── verifier.ts # Verifier implementation
│ └── ...
├── rust-src/ # Rust WASM wrapper
│ ├── Cargo.toml # Rust dependencies
│ └── src/lib.rs # WASM bindings
├── pkg/ # Generated WASM files
├── dist/ # Compiled TypeScript
└── examples/ # Usage examples
```
## Advanced Usage
### Using with React
```typescript
import { useEffect, useState } from 'react';
import LambdaWorksGroth16 from 'lambdaworks-groth16-ts';
function ProofGenerator() {
const [groth16, setGroth16] = useState<LambdaWorksGroth16 | null>(null);
const [proof, setProof] = useState<string | null>(null);
useEffect(() => {
LambdaWorksGroth16.init().then(setGroth16);
}, []);
const generateProof = async () => {
if (!groth16) return;
// Load your circuit and generate proof
const inputs = { secret: "42" };
const proof = await groth16.prover.proveWithInputs(circuit, provingKey, inputs);
setProof(groth16.prover.exportProof(proof, 'json'));
};
return (
<div>
<button onClick={generateProof} disabled={!groth16}>
Generate Proof
</button>
{proof && <pre>{proof}</pre>}
</div>
);
}
```
### Integration with Ethereum
```typescript
import { ethers } from 'ethers';
// Export proof for Solidity verification
const solidityProof = groth16.prover.exportProof(proof, 'solidity');
const vkJson = groth16.setupManager.exportVerifyingKey(setup.verifyingKey);
// Call verifier contract
const contract = new ethers.Contract(verifierAddress, verifierABI, signer);
const isValid = await contract.verifyProof(
solidityProof[0], // a
solidityProof[1], // b
solidityProof[2], // c
publicSignals
);
```
### Performance Optimization
```typescript
// Preload WASM for faster initialization
const wasmPromise = LambdaWorksGroth16.init();
// Use batch verification for multiple proofs
const results = groth16.verifier.batchVerify(vk, proofBatch);
// Reuse proving key for multiple proofs
const pk = setup.provingKey;
const proof1 = await groth16.prover.prove(circuit, pk, witness1);
const proof2 = await groth16.prover.prove(circuit, pk, witness2);
```
## Security Considerations
### Trusted Setup
⚠️ **CRITICAL**: Never use `generateUnsafeSetup()` in production. Always use setup parameters from a trusted ceremony.
```typescript
// ❌ DON'T DO THIS IN PRODUCTION
const setup = groth16.setupManager.generateUnsafeSetup(circuit);
// ✅ Use ceremony setup instead
const powersOfTau = await loadCeremonyFile('powers_of_tau.ptau');
const setup = await groth16.setupManager.loadSetup(powersOfTau, circuitSetup);
```
### Input Validation
Always validate inputs before proof generation:
```typescript
// Validate circuit constraints
if (!groth16.circuitProcessor.validateWitness(circuit, witness)) {
throw new Error('Invalid witness');
}
// Sanitize user inputs
const sanitizedInputs = Object.fromEntries(
Object.entries(userInputs).map(([k, v]) => [k, sanitizeFieldElement(v)])
);
```
## Supported Curves
- BN254 (bn128) - Default, Ethereum compatible
- BLS12-381 - High security applications
## Browser Compatibility
- Chrome 57+
- Firefox 52+
- Safari 11+
- Edge 16+
## Node.js Compatibility
- Node.js 14+
- Full ESM and CommonJS support
## Contributing
1. Fork the repository
2. Create feature branch: `git checkout -b feature/amazing-feature`
3. Commit changes: `git commit -m 'Add amazing feature'`
4. Push to branch: `git push origin feature/amazing-feature`
5. Open Pull Request
## Testing
```bash
# Run all tests
npm test
# Run specific test suite
npm test -- --testNamePattern="Prover"
# Run with coverage
npm test -- --coverage
```
## Benchmarks
Performance on various platforms:
| Platform | Proof Generation | Verification |
|----------|------------------|--------------|
| Chrome M1 Mac | ~2.1s | ~15ms |
| Node.js x64 | ~1.8s | ~12ms |
| Firefox x64 | ~2.4s | ~18ms |
*Benchmarks for 2^16 constraint circuit*
## License
MIT License - see [LICENSE](LICENSE) for details.
## Acknowledgments
- [LambdaClass](https://lambdaclass.com) for the core Rust implementation
- [Circom](https://circom.io) for circuit compilation tools
- [SnarkJS](https://github.com/iden3/snarkjs) for inspiration on API design
---
**Package Maintenance Status**: 🟢 Actively maintained
For issues and support, please visit our [GitHub repository](https://github.com/your-org/lambdaworks-groth16-ts).