# Privacy Framework: Wallet Developer Guide This comprehensive guide is designed for wallet development teams to implement Privacy Framework compatibility. It provides technical specifications, implementation patterns, and best practices for building privacy-preserving wallet functionality. ## Table of Contents - [Overview for Developers](#overview-for-developers) - [Technical Requirements](#technical-requirements) - [Implementation Guide](#implementation-guide) - [Privacy Storage Implementation](#privacy-storage-implementation) - [API Specifications](#api-specifications) - [Security Implementation](#security-implementation) - [Testing and Validation](#testing-and-validation) - [Performance Optimization](#performance-optimization) - [Integration Examples](#integration-examples) - [Deployment Checklist](#deployment-checklist) ## Overview for Developers Privacy Framework enables anonymous transactions on Starknet through zero-knowledge proofs and local data storage. This guide helps wallet developers implement privacy-preserving functionality. ### Key Concepts for Wallet Developers **Privacy Model**: Commitment-nullifier scheme where: - **On-chain**: Only cryptographic commitments and nullifiers are stored - **Off-chain**: All sensitive data (secrets, amounts, recipients) stays in local wallet storage - **Zero-Knowledge Proofs**: Validate operations without revealing private information **Your Role as Wallet Developer**: 1. **Local Storage Management**: Securely store privacy operation data 2. **Encryption**: Encrypt all privacy-related data before storage 3. **Key Derivation**: Generate encryption keys from wallet account 4. **Proof Generation**: Support ZK proof creation and submission 5. **User Experience**: Provide intuitive privacy operation interfaces ### Why Local Storage is Critical Privacy depends entirely on keeping sensitive data local. Your wallet must: - Store operation secrets that generate commitments and nullifiers - Maintain local Merkle tree state for efficient proof generation - Keep transaction history encrypted and accessible only to the user - Never transmit or store sensitive data on external servers ## Technical Requirements ### 1. Local Storage Infrastructure **Essential Requirements:** - **IndexedDB Support**: Primary storage for encrypted operation data - **Persistent Storage**: Data must survive browser sessions and updates - **Large Capacity**: Support for 50MB+ data (operations + Merkle tree + circuits) - **Encryption at Rest**: All sensitive data encrypted with wallet-derived keys **Storage Schema:** ```typescript interface PrivacyDatabase { operations: PrivacyOperation[]; merkleTree: MerkleTreeState; metadata: WalletMetadata; } interface PrivacyOperation { id: string; secret: string; // 32-byte random value nullifier: string; // poseidon_hash(secret, secret) commitment: string; // poseidon_hash(secret, nullifier, amount, token) amount: bigint; tokenAddress: string; status: 'pending' | 'confirmed' | 'nullified'; blockNumber?: number; transactionHash?: string; createdAt: Date; nullifiedAt?: Date; } ``` ### 2. Starknet Integration Requirements **Network Support:** - **Mainnet**: Full production support - **Sepolia Testnet**: Development and testing - **Custom Networks**: Configurable RPC endpoints **Transaction Capabilities:** - **Multi-call Support**: Batch operations in single transaction - **Large Proof Submission**: Support for 32KB+ ZK proofs - **Gas Estimation**: Accurate estimates for privacy operations - **Fee Management**: Handle STRK fee payments for privacy transactions ### 3. Cryptographic Requirements **Encryption Standards:** - **Algorithm**: AES-256-GCM for symmetric encryption - **Key Derivation**: PBKDF2 with 100,000 iterations - **Salt**: Fixed application-specific salt - **IV**: Unique per encrypted record **Zero-Knowledge Proof Support:** - **Noir.js Integration**: For circuit execution - **BB.js Integration**: For proof generation - **WASM Support**: Browser-compatible proof generation - **Worker Threads**: Background proof generation ## Implementation Guide ### Step 1: Initialize Privacy Storage ```typescript class PrivacyWalletStorage { private db: IDBDatabase; private encryptionKey: CryptoKey; async initialize(account: Account): Promise<void> { // 1. Derive encryption key from wallet account this.encryptionKey = await this.deriveEncryptionKey(account); // 2. Initialize IndexedDB this.db = await this.openDatabase(); // 3. Create object stores if needed await this.setupSchema(); } private async deriveEncryptionKey(account: Account): Promise<CryptoKey> { // Sign deterministic message to get seed const seed = await account.signMessage("Privacy Framework Encryption Key v1"); // Import seed as key material const keyMaterial = await crypto.subtle.importKey( "raw", new TextEncoder().encode(seed), "PBKDF2", false, ["deriveKey"] ); // Derive AES key return crypto.subtle.deriveKey( { name: "PBKDF2", salt: new TextEncoder().encode("privacy-framework-salt-v1"), iterations: 100000, hash: "SHA-256" }, keyMaterial, { name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"] ); } } ``` ### Step 2: Implement Data Encryption ```typescript class EncryptionManager { private key: CryptoKey; constructor(key: CryptoKey) { this.key = key; } async encrypt(data: any): Promise<ArrayBuffer> { // 1. Serialize data const plaintext = JSON.stringify(data); // 2. Generate random IV const iv = crypto.getRandomValues(new Uint8Array(12)); // 3. Encrypt data const encrypted = await crypto.subtle.encrypt( { name: "AES-GCM", iv }, this.key, new TextEncoder().encode(plaintext) ); // 4. Combine IV + encrypted data const result = new Uint8Array(iv.length + encrypted.byteLength); result.set(iv); result.set(new Uint8Array(encrypted), iv.length); return result.buffer; } async decrypt(encryptedData: ArrayBuffer): Promise<any> { // 1. Extract IV and encrypted data const iv = new Uint8Array(encryptedData.slice(0, 12)); const encrypted = encryptedData.slice(12); // 2. Decrypt const decrypted = await crypto.subtle.decrypt( { name: "AES-GCM", iv }, this.key, encrypted ); // 3. Parse result const plaintext = new TextDecoder().decode(decrypted); return JSON.parse(plaintext); } } ``` ## Privacy Storage Implementation ### Database Schema Design ```typescript interface DatabaseSchema { // Store individual privacy operations operations: { key: string; // operation ID value: { encrypted: ArrayBuffer; // encrypted operation data timestamp: number; // creation timestamp status: string; // operation status }; }; // Store Merkle tree state merkleTree: { key: "current"; value: { encrypted: ArrayBuffer; // encrypted tree data lastUpdate: number; // last sync timestamp blockNumber: number; // last synced block }; }; // Store wallet metadata metadata: { key: string; // metadata type value: { encrypted: ArrayBuffer; // encrypted metadata version: number; // schema version }; }; } ``` ### Operation Storage Methods ```typescript class PrivacyOperationStorage { private encryption: EncryptionManager; private db: IDBDatabase; async storeOperation(operation: PrivacyOperation): Promise<void> { // 1. Encrypt operation data const encrypted = await this.encryption.encrypt(operation); // 2. Store in IndexedDB const transaction = this.db.transaction(['operations'], 'readwrite'); const store = transaction.objectStore('operations'); await store.put({ encrypted, timestamp: Date.now(), status: operation.status }, operation.id); // 3. Wait for transaction completion await new Promise((resolve, reject) => { transaction.oncomplete = () => resolve(undefined); transaction.onerror = () => reject(transaction.error); }); } async getOperation(operationId: string): Promise<PrivacyOperation | null> { const transaction = this.db.transaction(['operations'], 'readonly'); const store = transaction.objectStore('operations'); const result = await store.get(operationId); if (!result) return null; // Decrypt and return operation return await this.encryption.decrypt(result.encrypted); } async getAllOperations(): Promise<PrivacyOperation[]> { const transaction = this.db.transaction(['operations'], 'readonly'); const store = transaction.objectStore('operations'); const cursor = await store.openCursor(); const operations: PrivacyOperation[] = []; while (cursor) { const decrypted = await this.encryption.decrypt(cursor.value.encrypted); operations.push(decrypted); cursor.continue(); } return operations; } } ``` ## API Specifications ### Core Privacy Wallet API ```typescript interface PrivacyWalletAPI { // Initialization initializePrivacy(account: Account): Promise<void>; isPrivacyInitialized(): boolean; // Operation Management createDeposit(amount: bigint, tokenAddress: string): Promise<PrivacyOperation>; createWithdrawal(deposits: string[], recipient: string, amount: bigint): Promise<PrivacyTransaction>; createTransfer(deposits: string[], recipientHash: string, amount: bigint): Promise<PrivacyTransaction>; // Storage Management exportOperations(): Promise<EncryptedBackup>; importOperations(backup: EncryptedBackup): Promise<void>; getOperationHistory(): Promise<PrivacyOperation[]>; // Proof Generation generateProof(operation: PrivacyOperation): Promise<ZKProof>; verifyProof(proof: ZKProof): Promise<boolean>; // Utility Methods getReceivingHash(): Promise<string>; estimatePrivacyGas(operation: PrivacyOperation): Promise<bigint>; getPrivacyBalance(tokenAddress: string): Promise<bigint>; } ``` ### Event Interface ```typescript interface PrivacyWalletEvents { // Operation events operationCreated: (operation: PrivacyOperation) => void; operationConfirmed: (operationId: string, blockNumber: number) => void; operationNullified: (operationId: string) => void; // Proof generation events proofGenerationStarted: (operationId: string) => void; proofGenerationProgress: (operationId: string, progress: number) => void; proofGenerationCompleted: (operationId: string, proof: ZKProof) => void; proofGenerationFailed: (operationId: string, error: Error) => void; // Storage events storageQuotaWarning: (usedBytes: number, availableBytes: number) => void; backupRequired: (operationCount: number) => void; } ``` ## Security Implementation ### Key Security Considerations 1. **Encryption Key Management** - Keys derived from wallet account signatures - Never store keys in plaintext - Re-derive keys when needed - Clear keys from memory after use 2. **Data Protection** - Encrypt all privacy-related data - Use authenticated encryption (AES-GCM) - Unique IV for each encryption operation - Secure deletion of sensitive data 3. **Memory Security** - Clear sensitive data from variables after use - Use TypedArrays for sensitive data when possible - Avoid logging sensitive information - Implement secure random number generation ### Security Implementation Example ```typescript class SecurityManager { private static readonly ENCRYPTION_MESSAGE = "Privacy Framework Encryption Key v1"; private static readonly SALT = "privacy-framework-salt-v1"; static async deriveKey(account: Account): Promise<CryptoKey> { try { // Get deterministic seed from wallet const seed = await account.signMessage(this.ENCRYPTION_MESSAGE); // Derive key using PBKDF2 const keyMaterial = await crypto.subtle.importKey( "raw", new TextEncoder().encode(seed), "PBKDF2", false, ["deriveKey"] ); const key = await crypto.subtle.deriveKey( { name: "PBKDF2", salt: new TextEncoder().encode(this.SALT), iterations: 100000, hash: "SHA-256" }, keyMaterial, { name: "AES-GCM", length: 256 }, false, ["encrypt", "decrypt"] ); // Clear seed from memory seed.fill?.(0); return key; } catch (error) { throw new Error(`Key derivation failed: ${error.message}`); } } static secureRandom(length: number): Uint8Array { return crypto.getRandomValues(new Uint8Array(length)); } static clearSensitiveData(data: any): void { if (data && typeof data.fill === 'function') { data.fill(0); } } } ``` ## Testing and Validation ### Unit Test Framework ```typescript describe('Privacy Wallet Storage', () => { let storage: PrivacyWalletStorage; let mockAccount: Account; beforeEach(async () => { mockAccount = createMockAccount(); storage = new PrivacyWalletStorage(); await storage.initialize(mockAccount); }); describe('Operation Storage', () => { test('should store and retrieve operations', async () => { const operation = createMockOperation(); await storage.storeOperation(operation); const retrieved = await storage.getOperation(operation.id); expect(retrieved).toEqual(operation); }); test('should encrypt stored data', async () => { const operation = createMockOperation(); await storage.storeOperation(operation); // Verify data is encrypted in storage const rawData = await getRawStorageData(operation.id); expect(rawData).not.toContain(operation.secret); }); }); describe('Key Derivation', () => { test('should derive consistent keys', async () => { const key1 = await SecurityManager.deriveKey(mockAccount); const key2 = await SecurityManager.deriveKey(mockAccount); // Keys should be functionally equivalent const testData = new TextEncoder().encode("test"); const encrypted1 = await encrypt(testData, key1); const decrypted = await decrypt(encrypted1, key2); expect(decrypted).toEqual(testData); }); }); }); ``` ### Integration Testing ```typescript describe('Privacy Wallet Integration', () => { test('full privacy operation flow', async () => { const wallet = new PrivacyWallet(); const account = await createTestAccount(); // 1. Initialize privacy await wallet.initializePrivacy(account); expect(wallet.isPrivacyInitialized()).toBe(true); // 2. Create deposit const deposit = await wallet.createDeposit( parseEther("1.0"), ETH_TOKEN_ADDRESS ); expect(deposit.status).toBe('pending'); // 3. Generate proof const proof = await wallet.generateProof(deposit); expect(await wallet.verifyProof(proof)).toBe(true); // 4. Submit transaction const txHash = await wallet.submitTransaction(proof); expect(txHash).toBeDefined(); }); }); ``` ## Performance Optimization ### Storage Optimization ```typescript class StorageOptimizer { static async compressOperations(operations: PrivacyOperation[]): Promise<ArrayBuffer> { // Use compression library (e.g., pako, lz-string) const serialized = JSON.stringify(operations); return compress(serialized); } static async cleanupOldOperations(storage: PrivacyOperationStorage, maxAge: number): Promise<void> { const operations = await storage.getAllOperations(); const cutoff = Date.now() - maxAge; const toDelete = operations.filter(op => op.status === 'nullified' && op.nullifiedAt && op.nullifiedAt.getTime() < cutoff ); for (const operation of toDelete) { await storage.deleteOperation(operation.id); } } } ``` ### Proof Generation Optimization ```typescript class ProofOptimizer { private static proofCache = new Map<string, CachedProof>(); static async generateProofWithCaching(operation: PrivacyOperation): Promise<ZKProof> { const cacheKey = this.getOperationHash(operation); const cached = this.proofCache.get(cacheKey); if (cached && Date.now() - cached.timestamp < 3600000) { // 1 hour cache return cached.proof; } // Generate proof in worker thread const proof = await this.generateProofInWorker(operation); // Cache result this.proofCache.set(cacheKey, { proof, timestamp: Date.now() }); return proof; } private static async generateProofInWorker(operation: PrivacyOperation): Promise<ZKProof> { return new Promise((resolve, reject) => { const worker = new Worker('./proof-worker.js'); worker.postMessage({ operation }); worker.onmessage = (event) => { const { proof, error } = event.data; worker.terminate(); if (error) reject(new Error(error)); else resolve(proof); }; }); } } ``` ## Integration Examples ### Basic Wallet Integration ```typescript class MyWallet extends BaseWallet implements PrivacyWalletAPI { private privacyStorage: PrivacyWalletStorage; private isPrivacyReady = false; async initializePrivacy(account: Account): Promise<void> { this.privacyStorage = new PrivacyWalletStorage(); await this.privacyStorage.initialize(account); this.isPrivacyReady = true; this.emit('privacyInitialized'); } async createDeposit(amount: bigint, tokenAddress: string): Promise<PrivacyOperation> { if (!this.isPrivacyReady) { throw new Error('Privacy not initialized'); } // Generate operation secrets const secret = generateSecret(); const nullifier = poseidonHash([secret, secret]); const commitment = poseidonHash([secret, nullifier, amount, tokenAddress]); const operation: PrivacyOperation = { id: generateOperationId(), secret: secret.toString(), nullifier: nullifier.toString(), commitment: commitment.toString(), amount, tokenAddress, status: 'pending', createdAt: new Date() }; await this.privacyStorage.storeOperation(operation); this.emit('operationCreated', operation); return operation; } async getPrivacyBalance(tokenAddress: string): Promise<bigint> { const operations = await this.privacyStorage.getAllOperations(); return operations .filter(op => op.tokenAddress === tokenAddress && op.status === 'confirmed' ) .reduce((total, op) => total + op.amount, 0n); } } ``` ## Deployment Checklist ### Pre-Release Validation - [ ] **Storage Implementation** - [ ] IndexedDB properly initialized - [ ] Encryption/decryption working correctly - [ ] Data persistence across sessions verified - [ ] Storage quota management implemented - [ ] **Security Validation** - [ ] Key derivation tested with multiple accounts - [ ] Encryption uses AES-256-GCM with unique IVs - [ ] No sensitive data logged or exposed - [ ] Memory cleanup implemented - [ ] **Privacy Features** - [ ] Operation creation and storage working - [ ] Proof generation functional - [ ] Backup/restore implemented - [ ] Privacy balance calculation accurate - [ ] **Performance Testing** - [ ] Proof generation completes within acceptable time - [ ] Storage operations are responsive - [ ] Memory usage is reasonable - [ ] No memory leaks detected - [ ] **User Experience** - [ ] Privacy features clearly indicated in UI - [ ] Error handling provides helpful messages - [ ] Loading states during proof generation - [ ] Backup reminders implemented ### Production Considerations 1. **Monitoring and Analytics** - Track proof generation success rates - Monitor storage usage patterns - Measure operation completion times - Log privacy-related errors (without sensitive data) 2. **User Education** - Provide clear documentation on privacy features - Explain backup importance - Warn users about privacy limitations - Guide users through first privacy operation 3. **Support and Maintenance** - Plan for schema migrations - Implement debugging tools for developers - Provide troubleshooting guides - Monitor privacy framework updates ## Resources - [Privacy Framework Architecture](./ARCHITECTURE.md) - [User Guide](./USER_GUIDE.md) - [Developer Guide](./DEVELOPER_GUIDE.md) - [Security Best Practices](./SECURITY.md) For technical support or questions about wallet compatibility, please contact our development team or join our community channels. --- This guide provides comprehensive information for wallet development teams implementing Privacy Framework compatibility. Follow the implementation patterns and security guidelines to ensure robust privacy-preserving functionality.