|
| 1 | +# ZK Private Payments |
| 2 | + |
| 3 | +Private token transfers using ZK proofs to hide payment amounts. |
| 4 | + |
| 5 | +## Summary |
| 6 | + |
| 7 | +- Deposit: Public tokens → private balance commitment = `Poseidon(amount, blinding)` |
| 8 | +- Transfer: Send tokens privately (hidden amounts) with ZK proof |
| 9 | +- Withdraw: Private balance → public tokens |
| 10 | +- Nullifier prevents double-spend |
| 11 | + |
| 12 | +## Quick Start |
| 13 | + |
| 14 | +```bash |
| 15 | +./scripts/setup.sh |
| 16 | +cargo build-sbf |
| 17 | +cargo test-sbf |
| 18 | +``` |
| 19 | + |
| 20 | +## Source Structure |
| 21 | + |
| 22 | +``` |
| 23 | +src/ |
| 24 | +├── lib.rs # Program entry, instructions, accounts |
| 25 | +└── verifying_key.rs # Groth16 verifying key (7 public inputs) |
| 26 | +
|
| 27 | +circuits/ |
| 28 | +├── private_transfer.circom # Main transfer circuit |
| 29 | +├── compressed_account.circom # Account hash computation |
| 30 | +├── merkle_proof.circom # Merkle tree verification (26 levels) |
| 31 | +└── range_check.circom # Balance sufficiency checks |
| 32 | +
|
| 33 | +tests/ |
| 34 | +└── test.rs # E2E test with proof generation |
| 35 | +``` |
| 36 | + |
| 37 | +## Instructions |
| 38 | + |
| 39 | +| Instruction | Description | |
| 40 | +|-------------|-------------| |
| 41 | +| `initialize` | Create vault for token mint | |
| 42 | +| `deposit` | Deposit tokens, create balance commitment | |
| 43 | +| `create_balance_commitment` | Create commitment without token transfer (testing) | |
| 44 | +| `transfer` | Private transfer with ZK proof | |
| 45 | +| `withdraw` | Withdraw tokens by proving commitment ownership | |
| 46 | + |
| 47 | +## Compressed Accounts |
| 48 | + |
| 49 | +| Account | Seeds | Fields | |
| 50 | +|---------|-------|--------| |
| 51 | +| `BalanceCommitment` | `[b"balance", commitment]` | `mint_hashed`, `commitment` | |
| 52 | +| `NullifierAccount` | `[b"nullifier", nullifier]` | `nullifier` | |
| 53 | + |
| 54 | +## ZK Circuit (PrivateTransfer) |
| 55 | + |
| 56 | +**Public inputs** (7 signals): |
| 57 | +1. `owner_hashed` - Program ID hashed to BN254 field |
| 58 | +2. `merkle_tree_hashed` - State tree pubkey hashed |
| 59 | +3. `discriminator` - BalanceCommitment discriminator |
| 60 | +4. `mint_hashed` - Token mint hashed |
| 61 | +5. `expectedRoot` - Merkle tree root |
| 62 | +6. `nullifier` - Prevents double-spend |
| 63 | +7. `receiver_commitment` - Receiver's balance commitment |
| 64 | + |
| 65 | +**Private inputs**: |
| 66 | +- `sender_amount`, `sender_blinding` - Sender's balance preimage |
| 67 | +- `transfer_amount` - Amount to transfer |
| 68 | +- `new_sender_blinding`, `receiver_blinding` - New blinding factors |
| 69 | +- `leaf_index`, `account_leaf_index`, `address` - Account position |
| 70 | +- `pathElements[26]` - Merkle proof |
| 71 | + |
| 72 | +**Circuit constraints**: |
| 73 | +1. Verify sender knows preimage: `sender_commitment = Poseidon(sender_amount, sender_blinding)` |
| 74 | +2. Verify nullifier: `nullifier = Poseidon(sender_commitment, sender_blinding)` |
| 75 | +3. Range check: `sender_amount >= transfer_amount` (64-bit decomposition) |
| 76 | +4. Verify new sender commitment: `new_sender_commitment = Poseidon(sender_amount - transfer_amount, new_sender_blinding)` |
| 77 | +5. Verify receiver commitment: `receiver_commitment = Poseidon(transfer_amount, receiver_blinding)` |
| 78 | +6. Compute data_hash and account hash |
| 79 | +7. Verify Merkle proof against `expectedRoot` |
| 80 | + |
| 81 | +## Errors |
| 82 | + |
| 83 | +| Code | Name | Message | |
| 84 | +|------|------|---------| |
| 85 | +| 6000 | `ZeroAmount` | Zero amount | |
| 86 | +| 6001 | `Overflow` | Arithmetic overflow | |
| 87 | +| 6002 | `InsufficientFunds` | Insufficient funds in vault | |
| 88 | +| 6003 | `AccountNotEnoughKeys` | Not enough keys in remaining accounts | |
| 89 | +| 6004 | `InvalidProof` | Invalid proof | |
| 90 | + |
| 91 | +## Dependencies |
| 92 | + |
| 93 | +- Light Protocol SDK (compression, Merkle trees) |
| 94 | +- groth16-solana (on-chain proof verification) |
| 95 | +- circomlib (Poseidon, comparators) |
0 commit comments