@permissionless-technologies/upc-sdk
v0.3.0
Published
Universal Private Compliance SDK — Pluggable zero-knowledge attestation & ASP (Association Set Provider) framework
Maintainers
Readme
Universal Private Compliance (UPC)
Pluggable zero-knowledge attestation & ASP (Association Set Provider) framework for Ethereum.
Part of the Permissionless Technologies product family:
- UPD — Universal Private Dollar
- UPP — Universal Private Pool
- UPC — Universal Private Compliance (this package)
What is UPC?
UPC provides a standard interface for zero-knowledge compliance verification on Ethereum. It allows:
- Institutions to operate ASPs (Association Set Providers) — Merkle trees of approved identities
- Users to prove membership in an ASP via ZK proof without revealing their identity
- Protocols to require attestations (KYC, age, residency, sanctions clearance) through a pluggable interface
- Third parties to build custom attestation backends (Semaphore, WorldID, zkPass, etc.)
Security
Default: BLS12-381 (128-bit security).
UPC defaults to Poseidon hash over the BLS12-381 curve, providing 128-bit security that meets institutional audit requirements. BN254 (~100-bit security) is available as an opt-in alternative.
| Curve | Security | Use Case | |-------|----------|----------| | BLS12-381 (default) | 128-bit | Production, institutional compliance | | BN254 (opt-in) | ~100-bit | Legacy compatibility, testing |
The hash function is fully pluggable via the IHashFunction interface — you can use either curve, or implement your own.
Proof System: PLONK
UPC uses PLONK (not Groth16) to eliminate per-circuit trusted setup ceremonies. Phase 1 uses the Perpetual Powers of Tau community ceremony (18 BLS12-381 contributors). Phase 2 is fully deterministic — no toxic waste, no ceremony participants to audit. Long-term, STARKs (no setup at all) are supported via the pluggable hash interface.
Architecture
┌───────────────────────────────────────────────────┐
│ AttestationHub (on-chain) │
│ │
│ verify(verifierId, identity, proof) → bool │
│ │
├──────────┬──────────────┬──────────────┬──────────┤
│ │ │ │ │
│ MerkleASP│ Semaphore │ WorldID │ Custom │
│ Verifier │ Adapter │ Adapter │ Adapter │
└──────────┴──────────────┴──────────────┴──────────┘
┌───────────────────────────────────────────────────┐
│ Provider Interface (off-chain) │
│ │
│ IASPProvider { addMember, getRoot, getProof } │
│ │
├──────────┬──────────────┬──────────────┬──────────┤
│ │ │ │ │
│ Memory │ LocalStorage │ REST API │ Custom │
│ Provider │ Provider │ Provider │ Provider │
└──────────┴──────────────┴──────────────┴──────────┘Quick Start
npm install @permissionless-technologies/upc-sdkAs an ASP Operator
import { createASPClient, MemoryProvider } from '@permissionless-technologies/upc-sdk'
const asp = createASPClient({
provider: new MemoryProvider({ treeDepth: 20 }),
publicClient,
registryAddress: '0x...',
})
// Register your ASP on-chain
const aspId = await asp.register({ name: 'My KYC ASP', walletClient })
// Add approved members
await asp.addMember(identityCommitment)
// Publish the Merkle root on-chain
await asp.publishRoot({ walletClient })As a User (proving membership)
import { createASPClient, LocalStorageProvider } from '@permissionless-technologies/upc-sdk'
const asp = createASPClient({
provider: new LocalStorageProvider({ chainId: 1, aspId: 1n }),
publicClient,
registryAddress: '0x...',
})
// Generate a ZK membership proof
const proof = await asp.generateProof(myIdentity)
// → { root, pathElements, pathIndices }As a Protocol (verifying compliance)
import { IAttestationVerifier } from "@permissionless-technologies/upc/interfaces/IAttestationVerifier.sol";
contract MyProtocol {
IAttestationVerifier public attestationHub;
function doSomething(uint256 verifierId, uint256 identity, bytes calldata proof) external {
require(attestationHub.verify(identity, proof), "Attestation required");
// ... proceed with business logic
}
}ASP Service Interfaces
UPC defines standard interfaces for building ASP services. Implementations live in separate packages.
import type { IEventSource, IMembershipGate } from '@permissionless-technologies/upc-sdk/asp'| Interface | Purpose | Example Implementations |
|-----------|---------|----------------------|
| IEventSource | Where do addresses come from? | RpcEventSource, SubsquidEventSource, webhooks |
| IMembershipGate | Who gets whitelisted? | AllowAllGate, SanctionsGate, KYC provider |
| API Schema | Standard response types | /root, /proof/:addr, /members, /status |
Sub-packages
| Package | Description |
|---------|-------------|
| @permissionless-technologies/upc-sdk | Core SDK (this package) |
| @permissionless-technologies/upc-asp-whitelist | Auto-whitelist ASP service |
| @permissionless-technologies/upc-asp-kyc | KYC verification ASP (planned) |
| @permissionless-technologies/upc-asp-sanctions | Sanctions screening ASP (planned) |
Custom Providers
Implement IASPProvider to connect any storage backend:
import type { IASPProvider } from '@permissionless-technologies/upc-sdk'
class MyDatabaseProvider implements IASPProvider {
name = 'My Database'
treeDepth = 20
async addMember(identity: bigint): Promise<void> { /* ... */ }
async removeMember(identity: bigint): Promise<void> { /* ... */ }
async getMembers(): Promise<bigint[]> { /* ... */ }
async hasMember(identity: bigint): Promise<boolean> { /* ... */ }
async getRoot(): Promise<bigint> { /* ... */ }
async getMerkleProof(identity: bigint): Promise<MerkleProof> { /* ... */ }
}Documentation
- Getting Started
- Architecture
- ASP Lists
- Custom Providers
- Smart Contracts
- Running an ASP Service
- Protocol Integration
License
See LICENSE file.
