# πŸ¦€ zkip > Zero-knowledge proof library for proving IP location privacy. ## Changelog ### 0.1.0 * Initial release * ZK Proof Core implementation * CLI with `--ip`, `--exclude`, `--refresh` flags * EVM-compatible proofs (Groth16/PLONK) ## Privacy Model | Party | Sees IP? | Stores IP? | | :----------------- | :---------------------- | :--------- | | User | βœ… (their own) | N/A | | Your Server | βœ… (transient in memory) | ❌ No | | SP1 Prover Network | βœ… (during computation) | ❌ No | **Note**: The SP1 Prover Network is a compute service, not a blockchain. Inputs are processed in memory and discarded after proof generation. ## What is zkip? **zkip** is a zero-knowledge proof library for proving a user's IP address is **not** from a specified set of countries without revealing the actual IP address. Built with [SP1](https://github.com/succinctlabs/sp1) zkVM. ### Motivation Many businesses and developers end up storing IP addresses for various reasons: * Regulatory compliance (tax laws, content licensing, gambling restrictions) * Proving user location to auditors * Fraud prevention and geo-restrictions * Analytics and service customization But storing IP addresses creates privacy concerns and GDPR obligations. **What if you could prove location without storing the IP?** (For example: In France, digital service providers must charge VAT on all sales unless they can prove the customer's location. This typically requires storing IP addresses, which is a privacy concern.) **zkip's solution**: Generate a zero-knowledge proof that verifies "this IP is not from countries X, Y, Z" without revealing or storing the actual IP address. You get verifiable location proofs while keeping user data private. ## Installation ### Requirements * [Rust](https://rustup.rs/) * [SP1](https://docs.succinct.xyz/docs/sp1/getting-started/install) ### Clone the Repository ```sh git clone https://github.com/nahiiko/zkip.git cd zkip ``` ## Quick Start ### 1. Build the Program ```sh cd program && cargo prove build ``` Or let it build automatically when running the script. ### 2. Execute (No Proof) Test the logic without generating a proof: ```sh cargo run --release -- --execute --ip 8.8.8.8 --exclude FR,US ``` This runs the ZK circuit locally and outputs the result without generating a cryptographic proof. ### 3. Generate a Proof (Local) ```sh cargo run --release -- --prove --ip 8.8.8.8 --exclude FR ``` Local proving is slow (minutes to hours depending on hardware). For production, use the network. ### 4. Use the Prover Network The [Succinct Prover Network](https://docs.succinct.xyz/docs/sp1/prover-network/quickstart) provides fast, distributed proof generation. **Setup:** 1. Generate a key pair: `cast wallet new` (or export from Metamask) 2. Get [PROVE tokens](https://docs.succinct.xyz/docs/sp1/prover-network/quickstart) on Ethereum Mainnet 3. Deposit PROVE at [Succinct Explorer](https://explorer.succinct.xyz/) 4. Configure environment: ```sh cp .env.example .env ``` ```env SP1_PROVER=network NETWORK_PRIVATE_KEY=0x... # Your requester account private key ``` 5. Run: ```sh cargo run --release -- --prove --ip 8.8.8.8 --exclude FR ``` ## On-Chain Verification Coming soon... ## REST API Coming soon... ## Flow ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ User β”‚ β”‚ Your API β”‚ β”‚ SP1 Prover β”‚ β”‚ (0x123...) β”‚ β”‚ (zkip) β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”‚ POST /prove β”‚ β”‚ β”‚ {excluded: ["FR", "DE"], β”‚ β”‚ β”‚ wallet: "0x123..."} β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Άβ”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ Extract IP from TCP connection β”‚ β”‚ β”‚ Load IP-to-country range table β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ Private: IP + range table β”‚ β”‚ β”‚ Public: excluded countries β”‚ β”‚ β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Άβ”‚ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ ZK Circuit: β”‚ β”‚ β”‚ 1. Lookup IP β”‚ β”‚ β”‚ 2. Check country β”‚ β”‚ β”‚ 3. Output result β”‚ β”‚ β”‚ β”‚ β”‚ proof + is_excluded β”‚ β”‚ │◀─────────────────────────────────── β”‚ β”‚ β”‚ β”‚ Discard IP from memory β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ {proof, is_excluded, timestamp} β”‚ β”‚ │◀─────────────────────────────────── β”‚ β”‚ β”‚ β”‚ β”‚ Store proof for audit β”‚ β”‚ β”‚ (No IP ever stored) β”‚ β”‚ β”‚ β”‚ β”‚ ``` **Flow Steps:** 1. **User Request**: Client sends excluded countries list and wallet address 2. **IP Extraction**: Server extracts IP from TCP connection (transient, in memory only) 3. **Proof Generation**: SP1 Prover runs ZK circuit with: * **Private inputs**: User's IP address + full country range table * **Public inputs**: List of excluded countries 4. **Circuit Execution**: Proves IP is NOT in any excluded country 5. **Response**: Server returns proof and result, then discards IP from memory 6. **Audit Trail**: User stores proof for compliance (without revealing IP) ## Architecture Overview ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ ARCHITECTURE β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” POST /prove β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ {excluded: ["FR","DE"]} β”‚ β”‚ β”‚ User β”‚ ─────────────────────────▢ β”‚ Your API β”‚ β”‚ (Browser) β”‚ β”‚ (zkip) β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ IP: hidden β”‚ β”‚ Extracts IP from β”‚ β”‚ β”‚ β”‚ TCP connection β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ IP + country ranges β”‚ β”‚ β”‚ (private inputs) β”‚ β”‚ β–Ό β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ { β”‚ SP1 Prover β”‚ β”‚ β”‚ is_excluded: true, β”‚ (local or β”‚ β”‚ β”‚ proof: "0xabc...", β”‚ network) β”‚ β”‚ β”‚ timestamp: "..." β”‚ β”‚ β”‚ β”‚ } β”‚ Runs ZK circuit: β”‚ β”‚ β”‚ β”‚ IP βˆ‰ excluded? β”‚ β”‚ β”‚ ◀─────────────────────────── β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` ## API Reference ### Future Design ``` POST /prove Request: { "excluded_countries": ["FR", "DE", "IT"], // Countries to prove absence from "user_id": "0x123..." // Optional: wallet or identifier } Response: { "is_excluded": true, // IP not in any excluded country "proof": "0xabc...", // ZK proof "timestamp": "2025-12-18T12:00:00Z" } ```