ZK Architecture
ZK Proof Architecture
Section titled “ZK Proof Architecture”SIP uses Noir as the primary ZK circuit language for zero-knowledge proofs.
Overview
Section titled “Overview”SIP requires ZK proofs for three core operations:
- Funding Proof - Prove sufficient funds without revealing balance
- Validity Proof - Prove intent authorization without revealing sender
- Fulfillment Proof - Prove correct execution without revealing path
Framework Selection
Section titled “Framework Selection”Decision: Noir
Section titled “Decision: Noir”Noir provides the best balance of:
- Developer experience (Rust-like syntax)
- Backend flexibility (UltraPlonk, Groth16, Halo2)
- Universal setup (no per-circuit trusted setup)
- Rich standard library
Evaluation Matrix
Section titled “Evaluation Matrix”| Criteria | Circom | Noir | Halo2 |
|---|---|---|---|
| Security | 9/10 | 7/10 | 7/10 |
| DX | 5/10 | 9/10 | 4/10 |
| Performance | 9/10 | 7/10 | 8/10 |
| Trust Assumptions | 5/10 | 8/10 | 10/10 |
| Weighted Score | 7.05 | 7.75 | 6.55 |
Circuit Specifications
Section titled “Circuit Specifications”Funding Proof
Section titled “Funding Proof”Proves user has sufficient balance without revealing actual amount.
fn funding_proof( // Public inputs commitment_hash: pub Field, minimum_amount: pub u64,
// Private inputs actual_balance: u64, blinding_factor: Field,) { // Prove balance is sufficient assert(actual_balance >= minimum_amount);
// Prove commitment is correctly formed let computed = pedersen_commit( actual_balance as Field, blinding_factor ); assert(commitment_hash(computed) == commitment_hash);}Validity Proof
Section titled “Validity Proof”Proves intent is authorized without revealing sender.
fn validity_proof( // Public inputs intent_hash: pub Field, sender_commitment: pub Field,
// Private inputs sender_address: Field, signature: [u8; 64], blinding: Field,) { // Verify signature let is_valid = ecdsa_verify( sender_address, intent_hash, signature ); assert(is_valid);
// Verify sender commitment let address_hash = poseidon::hash_1([sender_address]); let computed = pedersen_commit(address_hash, blinding); assert(commitment_hash(computed) == sender_commitment);}Fulfillment Proof
Section titled “Fulfillment Proof”Proves solver correctly executed the swap.
fn fulfillment_proof( // Public inputs intent_id: pub Field, output_commitment: pub Field, min_output: pub u64, recipient_stealth: pub Field,
// Private inputs output_amount: u64, output_blinding: Field, tx_hash: Field,) { // Prove output meets minimum assert(output_amount >= min_output);
// Prove commitment correctness let computed = pedersen_commit( output_amount as Field, output_blinding ); assert(commitment_hash(computed) == output_commitment);
// Prove delivery to stealth address // (binding to tx_hash proves execution)}Standard Library
Section titled “Standard Library”Noir provides built-in support for:
| Primitive | Usage |
|---|---|
| Pedersen hash | Commitment scheme |
| SHA256 | Compatibility |
| Poseidon | Field-efficient hashing |
| ECDSA | Wallet signatures |
| EdDSA | Alternative signatures |
| Schnorr | Stealth derivation |
Architecture
Section titled “Architecture”┌────────────────────────────────────────┐│ SDK (TypeScript) ││ ┌──────────────────────────────────┐ ││ │ ProofProvider │ ││ │ ┌────────────┐ ┌─────────────┐ │ ││ │ │MockProvider│ │NoirProvider │ │ ││ │ └────────────┘ └─────────────┘ │ ││ └──────────────────────────────────┘ ││ │ │└───────────────────┼─────────────────────┘ │ ┌───────────┴───────────┐ │ │ ▼ ▼┌───────────────┐ ┌───────────────┐│ Mock Proofs │ │ Noir/NoirJS ││ (Testing) │ │ (Production) │└───────────────┘ └───────────────┘ │ ┌─────────┴─────────┐ │ │ ▼ ▼ ┌──────────┐ ┌──────────┐ │UltraPlonk│ │ Groth16 │ │ Backend │ │ Backend │ └──────────┘ └──────────┘SDK Integration
Section titled “SDK Integration”ProofProvider Interface
Section titled “ProofProvider Interface”interface ProofProvider { generateFundingProof(params: FundingProofParams): Promise<ProofResult> generateValidityProof(params: ValidityProofParams): Promise<ProofResult> generateFulfillmentProof(params: FulfillmentProofParams): Promise<ProofResult> verifyProof(proof: ZKProof, publicInputs: Field[]): Promise<boolean>}MockProofProvider
Section titled “MockProofProvider”For testing and development:
const sip = new SIP({ network: 'testnet', proofProvider: new MockProofProvider()})NoirProofProvider (Planned)
Section titled “NoirProofProvider (Planned)”For production:
const sip = new SIP({ network: 'mainnet', proofProvider: new NoirProofProvider({ wasmPath: '/circuits/funding.wasm', circuitPath: '/circuits/' })})Performance
Section titled “Performance”| Operation | Mock | Noir (estimated) |
|---|---|---|
| Funding proof gen | <1ms | 2-5s |
| Validity proof gen | <1ms | 2-5s |
| Fulfillment proof gen | <1ms | 2-5s |
| Verification | <1ms | ~10ms |
Browser Support
Section titled “Browser Support”NoirJS enables client-side proof generation:
import { compile, createProver } from '@noir-lang/noir_js'
// Load circuitconst circuit = await compile('/circuits/funding.nr')const prover = await createProver(circuit)
// Generate proof in browserconst proof = await prover.prove({ actual_balance: 1000n, blinding_factor: randomField(), commitment_hash: commitmentHash, minimum_amount: 500n})Risk Mitigation
Section titled “Risk Mitigation”| Risk | Mitigation |
|---|---|
| Less battle-tested | Simple circuits, formal verification |
| Performance gaps | Start with UltraPlonk, can switch |
| Smaller ecosystem | Core primitives well-supported |
Roadmap
Section titled “Roadmap”Current (v0.1.x)
Section titled “Current (v0.1.x)”- MockProofProvider for testing
- Circuit specifications defined
- ProofProvider interface stable
Planned (v0.2.x)
Section titled “Planned (v0.2.x)”- Noir circuit implementation
- NoirJS integration
- Browser proof generation
Future (v0.3.x)
Section titled “Future (v0.3.x)”- Recursive proofs for batching
- Alternative backends
- Formal verification