How It Works

Understanding the magic behind Inkognito Network's privacy guarantees.

The Complete Flow

Core Technologies

1. x402 Protocol

HTTP 402 Payment Required is a standard HTTP status code that was reserved for future payment systems. Inkognito Network revives it for Web3.

How x402 Works

Step 1: Client tries to access a resource

Complete Example
1POST /rpc HTTP/1.1
2Host: rpc.inkognito.network
3Content-Type: application/json
4
5{"jsonrpc":"2.0","id":1,"method":"getBalance","params":["..."]}

Step 2: Server requires payment

Complete Example
1HTTP/1.1 402 Payment Required
2Content-Type: application/json
3
4{
5  "invoice_id": "uuid-1234",
6  "recipient": "F66vHTuTVnCayD9wvfpN8Vvb7M8uEvFUfWfA2HPQJ5e6",
7  "amount": 10000,
8  "memo": "Inkognito RPC access",
9  "expires_at": 1234567890
10}

Step 3: Client makes payment and retries

Complete Example
1POST /rpc HTTP/1.1
2Host: rpc.inkognito.network
3X-PAYMENT: mode=zk; proof=...; public_signals=[...]
4Content-Type: application/json
5
6{"jsonrpc":"2.0","id":1,"method":"getBalance","params":["..."]}

Step 4: Server verifies and responds

Complete Example
1HTTP/1.1 200 OK
2X-Session-Token: sess_abc123
3X-Requests-Remaining: 99
4Content-Type: application/json
5
6{"jsonrpc":"2.0","id":1,"result":{"value":1234567890}}

2. Zero-Knowledge Proofs

Groth16 ZK-SNARKs allow us to prove statements without revealing the underlying data.

The Circuit

Our ZK circuit proves: "I own credits for commitment_hash H without revealing which wallet bought them."

Public Inputs:

  • commitment_hash: The hash identifying the credit account (public)
  • nullifier: One-time-use token to prevent replay attacks (public)

Private Inputs:

  • secret: Your secret commitment value (private)
  • counter: A counter to generate unique nullifiers (private)

Circuit Logic:

1. Verify: Hash(secret) == commitment_hash 2. Compute: nullifier = Hash(secret, counter) 3. Output: (commitment_hash, nullifier)

Why This Guarantees Privacy

  1. No Wallet Linkage: The on-chain credit account stores only commitment_hash, not your wallet address
  2. Unlinkable Usage: Each RPC call uses a different nullifier, so calls cannot be linked together
  3. Mathematical Proof: The ZK proof is cryptographically sound - impossible to fake without knowing the secret

3. Smart Contract Architecture

Our Solana program stores credits using Program Derived Addresses (PDAs) derived from commitment hashes.

Credit Account Structure

Complete Example
1pub struct CreditAccount {
2    // Hash of user's secret (NOT their wallet!)
3    pub commitment_hash: [u8; 32],
4
5    // Credits available
6    pub credits_remaining: u64,
7
8    // Credits used (for statistics)
9    pub credits_used: u64,
10
11    // Creation timestamp
12    pub created_at: i64,
13}

Key Point: This account deliberately does NOT store who deposited the funds!

Deposit Flow

Complete Example
1pub fn deposit(
2    ctx: Context<Deposit>,
3    commitment_hash: [u8; 32],
4    amount: u64,
5) -> Result<()> {
6    // Calculate credits
7    let credits = amount / PRICE_PER_CREDIT;
8
9    // Create PDA account derived from commitment_hash
10    let credit_account = &mut ctx.accounts.credit_account;
11    credit_account.commitment_hash = commitment_hash;
12    credit_account.credits_remaining = credits;
13
14    // Transfer SOL to treasury
15    // ... transfer logic ...
16
17    Ok(())
18}

Notice: No owner field! The account is identified only by commitment_hash.

Use Credit Flow

Complete Example
1pub fn use_credit(
2    ctx: Context<UseCredit>,
3    commitment_hash: [u8; 32],
4    nullifier: [u8; 32],
5) -> Result<()> {
6    // Verify caller is authorized server
7    require!(
8        ctx.accounts.authority.key() == server_config.authority,
9        ErrorCode::Unauthorized
10    );
11
12    // Verify commitment matches
13    require!(
14        credit_account.commitment_hash == commitment_hash,
15        ErrorCode::InvalidCommitment
16    );
17
18    // Decrement credits
19    credit_account.credits_remaining -= 1;
20    credit_account.credits_used += 1;
21
22    Ok(())
23}

Note: Nullifier tracking happens off-chain in Redis to prevent replay attacks while maintaining privacy.

Privacy Guarantees

1. Payment Unlinkability

Problem: Traditional RPC providers link your payments to your usage.

Solution: Credits are stored with commitment_hash only. The server verifies ZK proofs without knowing which wallet deposited funds.

2. Usage Unlinkability

Problem: Even with anonymous credits, multiple requests could be correlated.

Solution: Each request uses a unique nullifier. The server cannot link requests together.

3. No Metadata Leakage

Problem: IP addresses, timestamps, and request patterns leak information.

Solution: Use Inkognito Network through Tor or a VPN for complete metadata protection. The RPC layer is private; network layer is your responsibility.

Security Considerations

What We Protect Against

Payment Tracking: Server cannot link payments to usage ✅ Request Correlation: Multiple requests cannot be linked ✅ Wallet Identification: No way to identify which wallet is making requests ✅ Censorship: Server cannot block specific users (doesn't know who they are)

What We Don't Protect Against

Network Analysis: Use Tor/VPN to hide your IP address ❌ On-Chain Analysis: Blockchain transactions are public (use mixers if needed) ❌ Timing Attacks: Don't be the only user making requests at 3 AM ❌ Side Channels: Smart contract interactions reveal some activity patterns

Best Practices

  1. Use Tor or VPN to hide your IP address
  2. Generate unique commitments for different applications
  3. Don't reuse wallets that deposited credits for actual transactions
  4. Batch deposits with other users to improve anonymity set
  5. Use privacy-preserving wallets (like Elusiv) for deposits

Technical Specifications

ZK Circuit

  • Type: Groth16 SNARK
  • Curve: BN254 (alt_bn128)
  • Constraints: 762
  • Proof Size: 192 bytes
  • Verification Time: <12ms

Cryptographic Primitives

  • Hash Function: Poseidon (ZK-friendly)
  • Commitment Scheme: Hash(secret) = commitment_hash
  • Nullifier Derivation: Hash(secret || counter) = nullifier

On-Chain Storage

  • Network: Solana
  • Program ID: F7hoT4cMvyqBeTrBEknkf2QkUBezRCqHJWDEn8xpyVs9 (Devnet)
  • Account Rent: ~0.002 SOL per credit account
  • Credits Per Account: Unlimited (u64 max)

Next Steps