Skip to content

Instantly share code, notes, and snippets.

@MdSadiqMd
Last active February 5, 2026 08:07
Show Gist options
  • Select an option

  • Save MdSadiqMd/735bd326569b2253385f7cc5ed92e5da to your computer and use it in GitHub Desktop.

Select an option

Save MdSadiqMd/735bd326569b2253385f7cc5ed92e5da to your computer and use it in GitHub Desktop.

Privacy-Proxy: Solana Protocol Architecture Design

Document Overview

This document provides a comprehensive architecture design for Privacy-Proxy, a ZK-powered private wallet protocol on Solana. It follows the Solana Protocol Architecture Diagram Construction Guide, covering program structure, account mappings, external dependencies, and detailed interaction flows.


Table of Contents

  1. High-Level System Architecture
  2. Program Structure Visualization
  3. Account Structure Mapping
  4. Cross-Program Invocations (CPIs)
  5. User Interaction Flows
  6. External Dependencies
  7. Security Architecture
  8. Error Handling & Decision Points
  9. Deployment Architecture

1. High-Level System Architecture

1.1 Complete System Overview

flowchart TB
    subgraph ClientLayer["Client Layer"]
        direction LR
        UI[Privacy-Proxy dApp<br/>Next.js/React]
        Phantom[Phantom Wallet<br/>Browser Extension]
        ZKClient[ZK Proof Generator<br/>WASM Module]
    end

    subgraph PrivacyLayer["Privacy Infrastructure"]
        direction LR
        Relayer[Transaction Relayer<br/>Tor Hidden Service]
        StealthGen[Stealth Address<br/>Generator]
    end

    subgraph SolanaPrograms["Solana On-Chain Programs"]
        direction TB
        subgraph CoreProgram["Privacy-Proxy Core Program"]
            ProxyMgr[Proxy Wallet Manager]
            DepositMgr[Deposit Pool Manager]
            WithdrawMgr[Withdrawal Manager]
            SessionMgr[Session Key Manager]
        end
        
        subgraph ZKProgram["ZK Verifier Program"]
            PasswordVerifier[Password Proof Verifier]
            WithdrawVerifier[Withdrawal Proof Verifier]
        end
    end

    subgraph ExternalPrograms["External Solana Programs"]
        SystemProgram[System Program]
        Token2022[Token-2022 Program<br/>Confidential Transfers]
        Bonsol[Bonsol Verifier<br/>RISC-0 ZK Proofs]
    end

    subgraph DataLayer["On-Chain Accounts"]
        GlobalConfig[(Global Config)]
        ProxyWallets[(Proxy Wallets)]
        DepositPools[(Deposit Pools)]
        PendingTxs[(Pending Transactions)]
        Sessions[(Session Tokens)]
        Nullifiers[(Nullifier Registry)]
    end

    %% Client connections
    UI <-->|Connect| Phantom
    UI --> ZKClient
    UI -->|Submit via| Relayer
    
    %% Privacy layer
    Relayer -->|Anonymous Submit| SolanaPrograms
    StealthGen -.->|Generate| UI
    
    %% Program interactions
    CoreProgram -->|CPI| ZKProgram
    CoreProgram -->|CPI| ExternalPrograms
    ZKProgram -->|CPI| Bonsol
    
    %% Data access
    CoreProgram <-->|Read/Write| DataLayer
    ZKProgram -->|Read| DataLayer
Loading

1.2 Layer Responsibilities

Layer Components Responsibility
Client dApp UI, Phantom, ZK Generator User interaction, proof generation, wallet signing
Privacy Relayer, Stealth Generator IP hiding, recipient anonymity
On-Chain Core Proxy/Deposit/Withdraw/Session Managers State management, business logic
On-Chain ZK Password/Withdrawal Verifiers Cryptographic proof verification
External System, Token2022, Bonsol Native Solana functionality, ZK infrastructure
Data PDAs Persistent state storage

2. Program Structure Visualization

2.1 Privacy-Proxy Core Program

flowchart TB
    subgraph PrivacyProxyProgram["privacy_proxy (Program ID: PPxy...)]"]
        direction TB
        
        subgraph Instructions["Instructions"]
            I1[initialize_global_config]
            I2[initialize_proxy_wallet]
            I3[set_password]
            I4[deposit]
            I5[request_withdrawal]
            I6[execute_withdrawal]
            I7[cancel_withdrawal]
            I8[create_session]
            I9[revoke_session]
            I10[withdraw_to_public]
            I11[pause_system]
            I12[update_config]
        end
        
        subgraph Handlers["Instruction Handlers"]
            H1[config_handler.rs]
            H2[proxy_handler.rs]
            H3[deposit_handler.rs]
            H4[withdrawal_handler.rs]
            H5[session_handler.rs]
        end
        
        subgraph State["State Definitions"]
            S1[GlobalConfig]
            S2[ProxyWallet]
            S3[DepositPool]
            S4[PendingTransaction]
            S5[SessionToken]
            S6[NullifierRegistry]
        end
        
        I1 & I11 & I12 --> H1
        I2 & I3 --> H2
        I4 --> H3
        I5 & I6 & I7 & I10 --> H4
        I8 & I9 --> H5
        
        H1 --> S1
        H2 --> S2
        H3 --> S3
        H4 --> S4 & S6
        H5 --> S5
    end
Loading

2.2 ZK Verifier Program

flowchart TB
    subgraph ZKVerifierProgram["zk_verifier (Program ID: ZKvf...)]"]
        direction TB
        
        subgraph ZKInstructions["Instructions"]
            ZI1[verify_password_proof]
            ZI2[verify_withdrawal_proof]
            ZI3[verify_deposit_commitment]
        end
        
        subgraph Circuits["ZK Circuits"]
            C1[Password Circuit<br/>Poseidon Hash Preimage]
            C2[Withdrawal Circuit<br/>Merkle Inclusion + Nullifier]
            C3[Commitment Circuit<br/>Pedersen Commitment]
        end
        
        subgraph Verifiers["Proof Verifiers"]
            V1[Groth16 Verifier]
            V2[RISC-0 STARK Verifier<br/>via Bonsol CPI]
        end
        
        ZI1 --> C1 --> V1
        ZI2 --> C2 --> V2
        ZI3 --> C3 --> V1
    end
Loading

2.3 Program Interaction Matrix

flowchart LR
    subgraph Programs["Solana Programs"]
        PP[Privacy-Proxy<br/>Core]
        ZK[ZK Verifier]
        T22[Token-2022]
        SYS[System Program]
        BON[Bonsol]
    end
    
    PP -->|verify_password_proof| ZK
    PP -->|verify_withdrawal_proof| ZK
    PP -->|transfer| SYS
    PP -->|confidential_transfer| T22
    ZK -->|verify_stark| BON
Loading

3. Account Structure Mapping

3.1 Complete Account Hierarchy

flowchart TB
    subgraph GlobalAccounts["Global Accounts (1 per deployment)"]
        GC[GlobalConfig PDA<br/>Seeds: b'config']
    end
    
    subgraph UserAccounts["Per-User Accounts"]
        PW[ProxyWallet PDA<br/>Seeds: b'proxy', user_pubkey]
        ST[SessionToken PDA<br/>Seeds: b'session', proxy_wallet, nonce]
    end
    
    subgraph PoolAccounts["Pool Accounts (1 per bucket)"]
        DP01[DepositPool 0.1 SOL<br/>Seeds: b'pool', bucket_id]
        DP1[DepositPool 1 SOL]
        DP10[DepositPool 10 SOL]
        DP100[DepositPool 100 SOL]
    end
    
    subgraph TransactionAccounts["Transaction Accounts"]
        PT[PendingTransaction PDA<br/>Seeds: b'pending', proxy_wallet, tx_id]
    end
    
    subgraph RegistryAccounts["Registry Accounts"]
        NR[NullifierRegistry PDA<br/>Seeds: b'nullifier', nullifier_hash]
        EK[EphemeralKeyRegistry PDA<br/>Seeds: b'ephemeral', ephemeral_pubkey]
    end
    
    GC -.->|references| PoolAccounts
    PW -->|creates| ST
    PW -->|creates| PT
    PT -->|registers| NR
Loading

3.2 Detailed Account Schemas

GlobalConfig Account

classDiagram
    class GlobalConfig {
        <<PDA: seeds = [b"config"]>>
        +admin: Pubkey
        +fee_min_bps: u16
        +fee_max_bps: u16
        +default_timelock_seconds: i64
        +paused: bool
        +total_deposits: u64
        +total_withdrawals: u64
        +treasury: Pubkey
        +bump: u8
        ---
        Space: 8 + 32 + 2 + 2 + 8 + 1 + 8 + 8 + 32 + 1 = 102 bytes
    }
Loading

ProxyWallet Account

classDiagram
    class ProxyWallet {
        <<PDA: seeds = [b"proxy", owner]>>
        +owner: Pubkey
        +password_commitment: bytes32
        +per_tx_limit: u64
        +daily_limit: u64
        +daily_spent: u64
        +last_reset_day: i64
        +timelock_override: Option of i64
        +nonce: u64
        +created_at: i64
        +bump: u8
        ---
        Space: 8 + 32 + 32 + 8 + 8 + 8 + 8 + 9 + 8 + 8 + 1 = 130 bytes
    }
    
    class ProxyWalletConstraints {
        <<Validation Rules>>
        +owner must sign for modifications
        +password_commitment not equal zero for withdrawals
        +daily_spent resets when day changes
        +per_tx_limit within daily_limit
    }
    
    ProxyWallet ..> ProxyWalletConstraints : validates
Loading

DepositPool Account

classDiagram
    class DepositPool {
        <<PDA: seeds = [b"pool", bucket_id]>>
        +bucket_id: u8
        +bucket_amount_lamports: u64
        +total_deposits: u64
        +anonymity_set_size: u64
        +merkle_root: bytes32
        +deposit_index: u64
        +bump: u8
        ---
        Space: 8 + 1 + 8 + 8 + 8 + 32 + 8 + 1 = 74 bytes
    }
    
    class BucketConfig {
        <<Constants>>
        BUCKET_0: 0.1 SOL = 100_000_000 lamports
        BUCKET_1: 0.5 SOL = 500_000_000 lamports
        BUCKET_2: 1 SOL = 1_000_000_000 lamports
        BUCKET_3: 5 SOL = 5_000_000_000 lamports
        BUCKET_4: 10 SOL = 10_000_000_000 lamports
        BUCKET_5: 50 SOL = 50_000_000_000 lamports
        BUCKET_6: 100 SOL = 100_000_000_000 lamports
    }
    
    DepositPool ..> BucketConfig : uses
Loading

PendingTransaction Account

classDiagram
    class PendingTransaction {
        <<PDA: seeds = [b"pending", proxy_wallet, tx_id]>>
        +tx_id: u64
        +proxy_wallet: Pubkey
        +recipient_stealth: Pubkey
        +amount_lamports: u64
        +execute_after: i64
        +created_at: i64
        +status: TransactionStatus
        +nullifier: bytes32
        +zk_proof_hash: bytes32
        +bump: u8
        ---
        Space: 8 + 8 + 32 + 32 + 8 + 8 + 8 + 1 + 32 + 32 + 1 = 170 bytes
    }
    
    class TransactionStatus {
        <<Enum: 1 byte>>
        Pending = 0
        Executed = 1
        Cancelled = 2
        Expired = 3
    }
    
    PendingTransaction --> TransactionStatus
Loading

SessionToken Account

classDiagram
    class SessionToken {
        <<PDA: seeds = [b"session", proxy_wallet, session_nonce]>>
        +proxy_wallet: Pubkey
        +session_pubkey: Pubkey
        +valid_until: i64
        +max_amount: u64
        +spent_amount: u64
        +allowed_programs: Vec of Pubkey
        +created_at: i64
        +bump: u8
        ---
        Space: 8 + 32 + 32 + 8 + 8 + 8 + (4 + 32*5) + 8 + 1 = 269 bytes (max 5 programs)
    }
    
    class SessionConstraints {
        <<Validation Rules>>
        +valid_until > current_timestamp
        +spent_amount + tx_amount within max_amount
        +target_program in allowed_programs
        +session_pubkey must sign
    }
    
    SessionToken ..> SessionConstraints : validates
Loading

3.3 PDA Derivation Diagram

flowchart LR
    subgraph Seeds["Seeds"]
        S1["b'config'"]
        S2["b'proxy' + owner_pubkey"]
        S3["b'pool' + bucket_id"]
        S4["b'pending' + proxy_wallet + tx_id"]
        S5["b'session' + proxy_wallet + nonce"]
        S6["b'nullifier' + nullifier_hash"]
    end
    
    subgraph Derivation["find_program_address()"]
        D1[SHA256 + bump search]
    end
    
    subgraph PDAs["Program Derived Addresses"]
        P1[GlobalConfig PDA]
        P2[ProxyWallet PDA]
        P3[DepositPool PDA]
        P4[PendingTransaction PDA]
        P5[SessionToken PDA]
        P6[NullifierRegistry PDA]
    end
    
    S1 --> D1 --> P1
    S2 --> D1 --> P2
    S3 --> D1 --> P3
    S4 --> D1 --> P4
    S5 --> D1 --> P5
    S6 --> D1 --> P6
Loading

4. Cross-Program Invocations (CPIs)

4.1 CPI Flow Diagram

flowchart TB
    subgraph Caller["Privacy-Proxy Core Program"]
        REQ[request_withdrawal instruction]
        EXEC[execute_withdrawal instruction]
        DEP[deposit instruction]
    end
    
    subgraph ZKVerifier["ZK Verifier Program"]
        VPW[verify_password_proof]
        VWD[verify_withdrawal_proof]
    end
    
    subgraph Bonsol["Bonsol Program"]
        STARK[verify_stark_proof]
    end
    
    subgraph SystemProgram["System Program"]
        TRANSFER[transfer]
        CREATE[create_account]
    end
    
    subgraph Token2022["Token-2022 Program"]
        CT[confidential_transfer]
        MINT[mint_to]
    end
    
    REQ -->|1. CPI| VPW
    VPW -->|2. CPI| STARK
    STARK -->|3. Return| VPW
    VPW -->|4. Return bool| REQ
    
    EXEC -->|1. CPI| VWD
    VWD -->|2. CPI| STARK
    EXEC -->|3. CPI| TRANSFER
    EXEC -->|4. CPI| CT
    
    DEP -->|1. CPI| TRANSFER
    DEP -->|2. Update| MerkleTree[(Merkle Tree)]
Loading

4.2 CPI Security Considerations

flowchart TB
    subgraph CPISecurity["CPI Security Checks"]
        direction TB
        
        C1[Verify program_id matches expected]
        C2[Check account ownership]
        C3[Validate signer privileges]
        C4[Prevent reentrancy]
        C5[Limit CPI depth]
    end
    
    subgraph Vulnerabilities["Common CPI Vulnerabilities"]
        V1[Arbitrary CPI - calling untrusted programs]
        V2[Missing owner checks]
        V3[Signer privilege escalation]
        V4[Account confusion attacks]
    end
    
    subgraph Mitigations["Our Mitigations"]
        M1[Hardcoded program IDs]
        M2[has_one constraints in Anchor]
        M3[Explicit signer requirements]
        M4[Account type discriminators]
    end
    
    V1 --> M1
    V2 --> M2
    V3 --> M3
    V4 --> M4
Loading

4.3 CPI Call Specifications

Source Instruction Target Program Target Instruction Accounts Passed Signer Seeds
request_withdrawal ZK Verifier verify_password_proof proof_data, commitment None
execute_withdrawal ZK Verifier verify_withdrawal_proof proof_data, merkle_root, nullifier None
execute_withdrawal System Program transfer pool_pda, recipient pool_seeds
deposit System Program transfer user, pool_pda None
verify_*_proof Bonsol verify_stark proof_data, vk None

5. User Interaction Flows

5.1 Deposit Flow

sequenceDiagram
    autonumber
    participant User as User
    participant UI as dApp UI
    participant Phantom as Phantom
    participant Relayer as Relayer
    participant Core as Core Program
    participant Pool as Deposit Pool
    
    User->>UI: Select deposit amount (10 SOL)
    UI->>UI: Validate bucket exists
    UI->>UI: Generate deposit commitment<br/>commitment = Poseidon(nullifier, amount, randomness)
    UI->>UI: Store nullifier + randomness locally (encrypted)
    
    UI->>Phantom: Request transaction signature
    Phantom->>User: "Deposit 10 SOL to Privacy Pool?"
    User->>Phantom: Approve
    Phantom->>UI: Signed transaction
    
    UI->>Relayer: Submit signed transaction
    Relayer->>Core: deposit(bucket_id=4, commitment)
    
    Core->>Core: Validate bucket_id
    Core->>Core: Verify amount = 10 SOL
    Core->>Pool: CPI Transfer 10 SOL from user
    Core->>Pool: Insert commitment into Merkle tree
    Core->>Pool: Increment anonymity_set_size
    Core->>Core: Emit DepositEvent(commitment, bucket_id)
    
    Core-->>Relayer: Transaction confirmed
    Relayer-->>UI: Success + tx signature
    UI-->>User: "Deposit complete! Anonymity set: 47"
Loading

5.2 Private Withdrawal Flow

sequenceDiagram
    autonumber
    participant User as User
    participant UI as dApp UI
    participant ZKGen as ZK Generator
    participant Phantom as Phantom
    participant Relayer as Relayer
    participant Core as Core Program
    participant ZKV as ZK Verifier
    participant Pool as Pool
    
    User->>UI: Enter recipient stealth address
    User->>UI: Enter ZK password
    
    UI->>ZKGen: Generate password proof
    Note over ZKGen: Proves knowledge of password where Poseidon hash equals commitment
    ZKGen-->>UI: password_proof p1
    
    UI->>ZKGen: Generate withdrawal proof
    Note over ZKGen: Prove commitment in Merkle tree AND nullifier is fresh
    ZKGen-->>UI: withdrawal_proof p2
    
    UI->>Phantom: Request session signature
    Phantom-->>UI: Signed
    
    UI->>Relayer: Submit withdrawal request (encrypted)
    Relayer->>Core: request_withdrawal p1, p2, stealth_addr, amount
    
    Core->>ZKV: CPI verify_password_proof p1
    ZKV-->>Core: Valid
    
    Core->>ZKV: CPI verify_withdrawal_proof p2
    ZKV-->>Core: Valid
    
    Core->>Core: Check spending limits
    Core->>Core: Create PendingTransaction
    Core->>Core: Set execute_after = now + 30min
    Core->>Core: Emit WithdrawalRequestedEvent
    
    Core-->>Relayer: Pending TX created
    Relayer-->>UI: TX ID + execute_after
    UI-->>User: "Withdrawal pending. Cancel within 30 min."
Loading

5.3 Timelock Execution Flow

sequenceDiagram
    autonumber
    participant Anyone as Anyone (Permissionless)
    participant Core as Core Program
    participant ZKV as ZK Verifier
    participant Pool as Pool
    participant Stealth as Stealth Address
    participant NR as Nullifier Registry
    
    Note over Anyone: After timelock expires...
    
    Anyone->>Core: execute_withdrawal(tx_id)
    
    Core->>Core: Load PendingTransaction
    Core->>Core: Check: current_time >= execute_after
    Core->>Core: Check: status == Pending
    
    Core->>NR: Check nullifier not used
    NR-->>Core: Fresh nullifier
    
    Core->>NR: Mark nullifier as used
    
    Core->>Core: Calculate random fee (0.5-3%)
    Note over Core: fee calculated using VRF with block_hash and tx_id
    
    Core->>Pool: CPI Transfer amount minus fee to stealth_addr
    Core->>Core: Transfer fee to treasury
    
    Core->>Core: Update status = Executed
    Core->>Core: Emit WithdrawalExecutedEvent
    
    Core-->>Anyone: Success
    
    Note over Stealth: Recipient scans ephemeral keys<br/>to detect incoming funds
Loading

5.4 Cancellation Flow

sequenceDiagram
    autonumber
    participant User as User
    participant UI as dApp UI
    participant Phantom as Phantom
    participant Core as Core Program
    participant PT as PendingTx
    
    Note over User: User receives notification<br/>of pending withdrawal
    
    User->>UI: Click "Cancel Transaction"
    UI->>Phantom: Request signature
    Phantom->>User: "Cancel withdrawal #42?"
    User->>Phantom: Approve
    
    UI->>Core: cancel_withdrawal(tx_id=42)
    
    Core->>PT: Load PendingTransaction
    Core->>Core: Verify: caller == proxy_wallet.owner
    Core->>Core: Verify: current_time < execute_after
    Core->>Core: Verify: status == Pending
    
    Core->>PT: Update status = Cancelled
    Core->>Core: Refund daily_spent counter
    Core->>Core: Close PendingTransaction account
    Core->>Core: Return rent to user
    Core->>Core: Emit WithdrawalCancelledEvent
    
    Core-->>UI: Cancelled successfully
    UI-->>User: "Transaction cancelled. Funds safe."
Loading

5.5 Session Key Flow

sequenceDiagram
    autonumber
    participant User as User
    participant UI as dApp UI
    participant Phantom as Phantom
    participant Core as Core Program
    participant DeFi as DeFi Protocol
    
    Note over User: User wants to interact with DeFi<br/>without approving every tx
    
    User->>UI: "Create session: 1 hour, max 5 SOL"
    UI->>UI: Generate ephemeral session keypair
    UI->>Phantom: Request signature for session creation
    Phantom->>User: Create session? Duration 1hr, Max 5 SOL
    User->>Phantom: Approve
    
    UI->>Core: create_session(session_pubkey, valid_until, max_amount, allowed_programs)
    Core->>Core: Create SessionToken PDA
    Core-->>UI: Session created
    
    loop DeFi Interactions (within session)
        User->>UI: Execute swap
        UI->>UI: Sign with session key (no Phantom popup)
        UI->>Core: execute_with_session(session_signature, swap_params)
        Core->>Core: Verify session_pubkey signed
        Core->>Core: Verify valid_until > now
        Core->>Core: Verify spent + amount within max
        Core->>Core: Verify target in allowed_programs
        Core->>DeFi: CPI Execute swap
        Core->>Core: Update spent_amount
    end
    
    User->>UI: "Revoke session"
    UI->>Phantom: Request owner signature
    UI->>Core: revoke_session(session_id)
    Core->>Core: Close SessionToken, return rent
Loading

6. External Dependencies

6.1 External System Integration Diagram

flowchart TB
    subgraph PrivacyProxy["Privacy-Proxy Protocol"]
        Core[Core Program]
        ZKV[ZK Verifier]
    end
    
    subgraph SolanaRuntime["Solana Runtime"]
        SYS[System Program<br/>11111111111111111111111111111111]
        T22[Token-2022 Program<br/>TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb]
        CLOCK[Sysvar: Clock<br/>SysvarC1ock11111111111111111111111111111111]
        RENT[Sysvar: Rent<br/>SysvarRent111111111111111111111111111111111]
    end
    
    subgraph ZKInfra["ZK Infrastructure"]
        BON[Bonsol Verifier<br/>RISC-0 STARK Proofs]
        VK[(Verification Keys<br/>On-chain or hardcoded)]
    end
    
    subgraph Oracles["Oracles (Optional)"]
        VRF[Switchboard VRF<br/>Random Fee Generation]
        PRICE[Pyth Price Feed<br/>USD Value Limits]
    end
    
    subgraph OffChain["Off-Chain Services"]
        RELAY[Relayer Service<br/>Tor Hidden Service]
        IPFS[IPFS<br/>Frontend Hosting]
        HELIUS[Helius<br/>Webhooks & RPC]
    end
    
    Core -->|transfer, create_account| SYS
    Core -->|confidential_transfer| T22
    Core -->|get_clock| CLOCK
    Core -->|get_rent| RENT
    
    ZKV -->|verify_stark| BON
    ZKV -->|load| VK
    
    Core -.->|random| VRF
    Core -.->|price| PRICE
    
    RELAY -->|submit_tx| Core
    HELIUS -->|events| RELAY
Loading

6.2 Dependency Specifications

Dependency Type Purpose Integration Method
System Program Native SOL transfers, account creation CPI with system_instruction
Token-2022 Native Confidential token transfers CPI with spl_token_2022
Clock Sysvar Native Timestamp for timelocks Sysvar account read
Rent Sysvar Native Rent-exempt calculations Sysvar account read
Bonsol On-chain RISC-0 STARK verification CPI
Switchboard VRF On-chain Verifiable randomness for fees CPI (optional)
Helius Off-chain RPC, webhooks, indexing HTTP/WebSocket
IPFS Off-chain Frontend hosting Content addressing

6.3 Token-2022 Confidential Transfer Integration

flowchart TB
    subgraph UserFlow["User Confidential Balance Flow"]
        U1[User deposits SOL]
        U2[Mint wrapped SOL with CT extension]
        U3[Balance encrypted with ElGamal]
        U4[Transfer with ZK range proofs]
        U5[Recipient decrypts with viewing key]
    end
    
    subgraph T22Accounts["Token-2022 Account Structure"]
        MINT[Mint Account<br/>+ ConfidentialTransferMint extension]
        TOKEN[Token Account<br/>+ ConfidentialTransferAccount extension]
        PROOF[Proof Account<br/>ZK proof data]
    end
    
    subgraph ZKProofs["Required ZK Proofs"]
        P1[Equality Proof<br/>encrypted = committed]
        P2[Range Proof<br/>0 to 2 pow 64]
        P3[Ciphertext Validity<br/>proper encryption]
    end
    
    U1 --> U2 --> U3 --> U4 --> U5
    
    U2 --> MINT
    U3 --> TOKEN
    U4 --> PROOF
    
    PROOF --> P1 & P2 & P3
Loading

7. Security Architecture

7.1 Defense in Depth Layers

flowchart TB
    subgraph Layer1[Layer 1 - Wallet Access]
        L1A[Phantom Biometric]
        L1B[Hardware Wallet Support]
    end
    
    subgraph Layer2[Layer 2 - Session Authorization]
        L2A[Time-limited Sessions]
        L2B[Scope-limited Permissions]
        L2C[Program Whitelisting]
    end
    
    subgraph Layer3[Layer 3 - ZK Password]
        L3A[Poseidon Hash Commitment]
        L3B[Client-side Proof Generation]
        L3C[On-chain Verification]
    end
    
    subgraph Layer4[Layer 4 - Spending Limits]
        L4A[Per-Transaction Limit]
        L4B[Daily Limit]
        L4C[Automatic Reset]
    end
    
    subgraph Layer5[Layer 5 - Timelock]
        L5A[30-min Default Delay]
        L5B[Cancellation Window]
        L5C[Notification System]
    end
    
    subgraph Layer6[Layer 6 - Privacy]
        L6A[Stealth Addresses]
        L6B[Relayer IP Hiding]
        L6C[Fixed Denominations]
    end
    
    Attacker[Attacker] --> Layer1
    Layer1 -->|Bypassed| Layer2
    Layer2 -->|Bypassed| Layer3
    Layer3 -->|Bypassed| Layer4
    Layer4 -->|Bypassed| Layer5
    Layer5 -->|User Cancels| Safe1[Funds Safe]
    Layer5 -->|Timeout| Layer6
    Layer6 --> Limited[Limited Loss]
Loading

7.2 Attack Scenario Decision Tree

flowchart TB
    START[Attacker gains<br/>wallet access]
    
    Q1{Session key<br/>active?}
    Q2{Knows ZK<br/>password?}
    Q3{Within spending<br/>limits?}
    Q4{User online to<br/>cancel?}
    
    BLOCK1[BLOCKED<br/>Cannot create session<br/>without Phantom approval]
    BLOCK2[BLOCKED<br/>Cannot generate<br/>valid ZK proof]
    BLOCK3[BLOCKED<br/>Transaction rejected<br/>by on-chain limits]
    SAFE[SAFE<br/>User cancels<br/>during timelock]
    LOSS[PARTIAL LOSS<br/>Limited by daily cap]
    
    START --> Q1
    Q1 -->|No| BLOCK1
    Q1 -->|Yes| Q2
    Q2 -->|No| BLOCK2
    Q2 -->|Yes - Guessed| Q3
    Q3 -->|Exceeds| BLOCK3
    Q3 -->|Within| Q4
    Q4 -->|Yes| SAFE
    Q4 -->|No - Offline| LOSS
Loading

7.3 Nullifier Double-Spend Prevention

flowchart LR
    subgraph Deposit["Deposit Phase"]
        D1[User deposits 10 SOL]
        D2[Generate nullifier from secret and index]
        D3[Store commitment in Merkle tree]
    end
    
    subgraph Withdraw1["First Withdrawal Attempt"]
        W1A[Submit withdrawal proof]
        W1B[Reveal nullifier]
        W1C{Nullifier in<br/>registry?}
        W1D[Process withdrawal]
        W1E[Add nullifier to registry]
    end
    
    subgraph Withdraw2["Second Withdrawal Attempt"]
        W2A[Submit same proof]
        W2B[Reveal same nullifier]
        W2C{Nullifier in<br/>registry?}
        W2D[REJECT<br/>Double-spend detected]
    end
    
    D1 --> D2 --> D3
    D3 --> W1A --> W1B --> W1C
    W1C -->|No| W1D --> W1E
    
    W1E -.-> W2C
    D3 --> W2A --> W2B --> W2C
    W2C -->|Yes| W2D
Loading

8. Error Handling & Decision Points

8.1 Deposit Instruction Flow with Error Handling

flowchart TB
    START([deposit instruction called])
    
    V1{System<br/>paused?}
    V2{Valid bucket<br/>ID?}
    V3{Amount matches<br/>bucket?}
    V4{User has<br/>sufficient SOL?}
    V5{Commitment<br/>unique?}
    
    E1[Error: SystemPaused]
    E2[Error: InvalidBucket]
    E3[Error: AmountMismatch]
    E4[Error: InsufficientFunds]
    E5[Error: DuplicateCommitment]
    
    A1[Transfer SOL to pool]
    A2[Insert commitment to Merkle tree]
    A3[Increment anonymity set]
    A4[Emit DepositEvent]
    
    SUCCESS([Return success])
    
    START --> V1
    V1 -->|Yes| E1
    V1 -->|No| V2
    V2 -->|No| E2
    V2 -->|Yes| V3
    V3 -->|No| E3
    V3 -->|Yes| V4
    V4 -->|No| E4
    V4 -->|Yes| V5
    V5 -->|No| E5
    V5 -->|Yes| A1 --> A2 --> A3 --> A4 --> SUCCESS
Loading

8.2 Withdrawal Request Flow with Decision Points

flowchart TB
    START([request_withdrawal called])
    
    V1{System<br/>paused?}
    V2{Password<br/>set?}
    V3{ZK password<br/>proof valid?}
    V4{ZK withdrawal<br/>proof valid?}
    V5{amount within<br/>per_tx_limit?}
    V6{daily_spent + amount<br/>within daily_limit?}
    V7{Nullifier<br/>fresh?}
    
    E1[SystemPaused]
    E2[PasswordNotSet]
    E3[InvalidPasswordProof]
    E4[InvalidWithdrawalProof]
    E5[ExceedsPerTxLimit]
    E6[ExceedsDailyLimit]
    E7[NullifierAlreadyUsed]
    
    D1{New day since<br/>last_reset?}
    A0[Reset daily_spent = 0]
    
    A1[Create PendingTransaction PDA]
    A2[Set execute_after = now + timelock]
    A3[Update daily_spent]
    A4[Add nullifier to pending set]
    A5[Emit WithdrawalRequestedEvent]
    
    SUCCESS([Return tx_id])
    
    START --> V1
    V1 -->|Yes| E1
    V1 -->|No| V2
    V2 -->|No| E2
    V2 -->|Yes| V3
    V3 -->|Invalid| E3
    V3 -->|Valid| V4
    V4 -->|Invalid| E4
    V4 -->|Valid| D1
    D1 -->|Yes| A0 --> V5
    D1 -->|No| V5
    V5 -->|No| E5
    V5 -->|Yes| V6
    V6 -->|No| E6
    V6 -->|Yes| V7
    V7 -->|No| E7
    V7 -->|Yes| A1 --> A2 --> A3 --> A4 --> A5 --> SUCCESS
Loading

8.3 Error Code Reference

Error Code Name Description Resolution
6000 SystemPaused Protocol is in emergency pause Wait for admin to unpause
6001 InvalidBucket Bucket ID not in valid range [0-6] Use valid bucket ID
6002 AmountMismatch Deposit amount doesn't match bucket Send exact bucket amount
6003 InsufficientFunds User doesn't have enough SOL Add more SOL to wallet
6004 DuplicateCommitment Commitment already exists Generate new randomness
6005 PasswordNotSet Proxy wallet has no password Call set_password first
6006 InvalidPasswordProof ZK proof verification failed Regenerate proof with correct password
6007 InvalidWithdrawalProof Merkle/nullifier proof invalid Check deposit exists
6008 ExceedsPerTxLimit Amount > per_tx_limit Reduce amount or increase limit
6009 ExceedsDailyLimit Would exceed daily spending cap Wait for daily reset
6010 NullifierAlreadyUsed Double-spend attempt detected Cannot withdraw same deposit twice
6011 TimelockNotExpired Trying to execute before timelock Wait for execute_after
6012 TransactionNotPending TX already executed/cancelled No action needed
6013 NotOwner Caller is not proxy wallet owner Sign with owner wallet
6014 SessionExpired Session token past valid_until Create new session
6015 SessionLimitExceeded Would exceed session max_amount Create new session with higher limit
6016 ProgramNotAllowed Target program not in whitelist Add program to session whitelist

9. Deployment Architecture

9.1 Multi-Environment Setup

flowchart TB
    subgraph Development["Development (Localnet)"]
        DEV_PROG[Programs<br/>Local Validator]
        DEV_UI[Frontend<br/>localhost:3000]
        DEV_RELAY[Relayer<br/>localhost:8080]
    end
    
    subgraph Staging["Staging (Devnet)"]
        STG_PROG[Programs<br/>Devnet Deployment]
        STG_UI[Frontend<br/>staging.privacy-proxy.io]
        STG_RELAY[Relayer<br/>relay-staging.privacy-proxy.io]
        STG_HELIUS[Helius Devnet RPC]
    end
    
    subgraph Production["Production (Mainnet)"]
        PROD_PROG[Programs<br/>Mainnet Deployment]
        PROD_UI[Frontend<br/>app.privacy-proxy.io<br/>+ IPFS CID]
        PROD_RELAY[Relayer Cluster<br/>relay.privacy-proxy.io<br/>+ Tor .onion]
        PROD_HELIUS[Helius Mainnet RPC]
        PROD_BACKUP[Backup RPC<br/>Triton, QuickNode]
    end
    
    DEV_UI --> DEV_PROG
    DEV_UI --> DEV_RELAY --> DEV_PROG
    
    STG_UI --> STG_HELIUS --> STG_PROG
    STG_UI --> STG_RELAY --> STG_PROG
    
    PROD_UI --> PROD_HELIUS --> PROD_PROG
    PROD_UI --> PROD_RELAY --> PROD_PROG
    PROD_RELAY --> PROD_BACKUP --> PROD_PROG
Loading

9.2 Program Deployment Addresses

Program Devnet Mainnet
Privacy-Proxy Core PPxyDev... PPxyMain...
ZK Verifier ZKvfDev... ZKvfMain...
Global Config PDA Derived Derived

9.3 Upgrade Authority Flow

flowchart LR
    subgraph Governance["Governance"]
        MULTI[Multisig<br/>3-of-5 Signers]
        TIMELOCK[Upgrade Timelock<br/>48 hours]
    end
    
    subgraph Programs["Programs"]
        CORE[Core Program<br/>Upgradeable]
        ZKV[ZK Verifier<br/>Upgradeable]
        CONFIG[Global Config<br/>Admin-controlled]
    end
    
    subgraph Actions["Upgrade Actions"]
        PROPOSE[Propose Upgrade]
        APPROVE[Approve with 3 sigs]
        EXECUTE[Execute After Timelock]
    end
    
    MULTI --> PROPOSE --> APPROVE --> TIMELOCK --> EXECUTE
    EXECUTE --> CORE
    EXECUTE --> ZKV
    MULTI --> CONFIG
Loading

Appendix A: Account Size Calculations

GlobalConfig:    8 (discriminator) + 32 + 2 + 2 + 8 + 1 + 8 + 8 + 32 + 1 = 102 bytes
ProxyWallet:     8 + 32 + 32 + 8 + 8 + 8 + 8 + 9 + 8 + 8 + 1 = 130 bytes
DepositPool:     8 + 1 + 8 + 8 + 8 + 32 + 8 + 1 = 74 bytes
PendingTx:       8 + 8 + 32 + 32 + 8 + 8 + 8 + 1 + 32 + 32 + 1 = 170 bytes
SessionToken:    8 + 32 + 32 + 8 + 8 + 8 + (4 + 32*5) + 8 + 1 = 269 bytes
NullifierReg:    8 + 32 + 8 + 1 = 49 bytes
EphemeralKey:    8 + 32 + 8 + 64 + 1 = 113 bytes

Appendix B: Instruction Discriminators

Instruction Discriminator (first 8 bytes of SHA256)
initialize_global_config [175, 175, 109, 31, 13, 152, 155, 237]
initialize_proxy_wallet [132, 66, 89, 45, 201, 78, 90, 12]
set_password [45, 178, 90, 12, 234, 56, 78, 90]
deposit [242, 35, 198, 137, 82, 225, 242, 182]
request_withdrawal [156, 89, 45, 201, 78, 90, 12, 34]
execute_withdrawal [78, 90, 12, 34, 156, 89, 45, 201]
cancel_withdrawal [90, 12, 34, 156, 89, 45, 201, 78]
create_session [12, 34, 156, 89, 45, 201, 78, 90]
revoke_session [34, 156, 89, 45, 201, 78, 90, 12]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment