+×+

Privacy Technologies

Protocol 01 combines cutting-edge cryptography to deliver true financial privacy on Solana.Every component is built from scratch for maximum security and efficiency.

System Architecture

+×+

System Architecture

Protocol Stack

Client Layer
MOBILE APP
React Native
EXTENSION
Chrome / Brave
SDK
TypeScript
ZK-SDK
WASM Prover
Groth16
Poseidon
Hash Function
Note Mgmt
Encrypt / Decrypt
Protocol Layer
STEALTH
ECDH Addresses
SHIELDED
Groth16 Pool
STREAMS
SPL Payments
Relay Layer
RELAYER
ZK Verify + Transfer
ON-CHAIN
Solana Program
Solana Blockchain
alt_bn128
Curve Ops
SPL Tokens
Token Standard
Anchor
Framework
End-to-end encrypted
|
From client to settlement

Core Technologies

Stealth Addresses (ECDH)

Stealth addresses allow recipients to receive funds without revealing their public address. Each payment creates a unique one-time address using Elliptic Curve Diffie-Hellman key exchange.

Key Features

  • Sender generates ephemeral keypair for each transaction
  • Shared secret computed using ECDH between sender ephemeral key and recipient's public key
  • One-time address derived: P = H(shared_secret) * G + recipient_pubkey
  • Only the recipient can detect and spend funds using their private key
  • Implemented using Curve25519 for efficiency on Solana

Code Example

// Generate stealth address
const ephemeral = Keypair.generate();
const sharedSecret = x25519(ephemeral.secretKey, recipientPubkey);
const stealthKey = deriveStealthKey(sharedSecret, recipientPubkey);

Zero-Knowledge Proofs (Groth16)

ZK-SNARKs enable private transfers where amounts and participants are hidden. We use Groth16 proofs verified on-chain using Solana's native alt_bn128 syscalls.

Key Features

  • Circom circuits with ~12,000 constraints for efficient proving
  • Poseidon hash function (ZK-friendly) for commitments and Merkle trees
  • Groth16 verification using Solana's native BN254 pairing precompiles
  • Proof generation takes <2 seconds on modern devices
  • Trusted setup completed with secure MPC ceremony

Code Example

// Generate ZK proof for private transfer
const { proof, publicSignals } = await snarkjs.groth16.fullProve(
  { inputs, merkle_path, nullifiers },
  "transfer.wasm",
  "transfer.zkey"
);

Shielded Pool Architecture

The shielded pool stores encrypted notes in a Merkle tree. Users can deposit (shield), transfer privately, and withdraw (unshield) while maintaining complete privacy.

Key Features

  • Note = Hash(amount, owner_pubkey, randomness, token_mint)
  • Sparse Merkle tree with depth 20 (~1M notes capacity)
  • Nullifiers prevent double-spending without revealing which note was spent
  • Historical roots accepted for concurrent transactions
  • Supports SOL and any SPL token

Code Example

// Shielded note structure
Note = {
  amount: u64,           // Hidden from observers
  owner_pubkey: [u8; 32], // Derived from spending key
  randomness: [u8; 32],   // Blinding factor
  commitment: Poseidon(amount, owner, randomness, mint)
}

Poseidon Hash Function

Poseidon is a ZK-friendly hash function designed specifically for use inside arithmetic circuits. It's significantly more efficient than traditional hashes like SHA-256 or Keccak in ZK contexts.

Key Features

  • Operates natively over prime fields (BN254 scalar field)
  • ~300x fewer constraints than Keccak in Circom circuits
  • Used for note commitments and Merkle tree hashing
  • Parameters: BN254 curve, x^5 S-box, 8 full rounds
  • Compatible with circomlib implementation

Code Example

// Poseidon hash in circuit
template NoteCommitment() {
    signal input amount;
    signal input ownerPubkey;
    signal input randomness;
    signal output commitment;

    component hash = Poseidon(4);
    hash.inputs[0] <== amount;
    hash.inputs[1] <== ownerPubkey;
    hash.inputs[2] <== randomness;
    hash.inputs[3] <== tokenMint;
    commitment <== hash.out;
}

Merkle Tree Proofs

A Merkle tree stores all note commitments, allowing users to prove membership without revealing which note they own. The root is stored on-chain and updated with each deposit.

Key Features

  • Binary tree with Poseidon hash at each node
  • Depth 20 = 2^20 = ~1 million notes capacity
  • Proof size: 20 siblings + 20 path indices
  • Incremental insertions for gas efficiency
  • Precomputed zero values for empty subtrees

Code Example

// Merkle proof verification in circuit
for (var i = 0; i < TREE_DEPTH; i++) {
    left = pathIndices[i] == 0 ? current : siblings[i];
    right = pathIndices[i] == 0 ? siblings[i] : current;
    current = Poseidon(left, right);
}
root === computedRoot; // Must match on-chain root

Nullifier Mechanism

Nullifiers are unique identifiers that prevent double-spending without revealing which note was spent. Each note can only produce one valid nullifier.

Key Features

  • Nullifier = Poseidon(commitment, spending_key_hash)
  • Stored on-chain in a set (prevents reuse)
  • Cannot be linked back to the original note
  • Spending key proves ownership without revealing identity
  • Bloom filter optimization for gas efficiency

Code Example

// Nullifier computation
const spendingKeyHash = Poseidon([spendingKey]);
const nullifier = Poseidon([commitment, spendingKeyHash]);
// On-chain: require(!nullifierSet.contains(nullifier))

Solana On-Chain Verification

Protocol 01 leverages Solana's native cryptographic syscalls for efficient on-chain ZK proof verification, achieving verification in under 200K compute units.

Key Features

  • alt_bn128 syscalls for BN254 curve operations
  • Native pairing checks for Groth16 verification
  • Anchor framework for type-safe program development
  • Compute budget: ~200K CU for full proof verification
  • Cross-program invocations for token transfers

Code Example

// On-chain Groth16 verification
let pairing_result = sol_alt_bn128_pairing(
    &[pi_a_neg, vk_alpha, pi_b, vk_beta, pi_c, vk_gamma, ...]
);
require!(pairing_result == 1, "Invalid proof");

Private Relay Architecture

User-funded relayer that verifies ZK proofs and executes private transfers to stealth addresses, breaking the on-chain link between sender and recipient.

Key Features

  • User funds relayer with transfer amount + fee (0.5%) + gas + rent
  • Relayer verifies ZK proof server-side (Groth16 snarkjs verification)
  • Relayer sends to stealth address — no on-chain link to the sender
  • Currently a self-hosted backend service (Node.js)
  • Roadmap: on-chain Solana program for fully decentralized relay

Code Example

// Private relay flow
// 1. User generates ZK proof client-side
const { proof, publicSignals } = await generateProof(inputs);

// 2. User funds relayer with amount + fee + gas
const fundTx = await fundRelayer(amount, fee, gasCost, rentCost);

// 3. Relayer verifies proof and sends to stealth address
// POST /api/private-send
{
  proof,           // Groth16 ZK proof
  publicSignals,   // Nullifier + commitments
  recipient,       // Stealth address (unlinkable)
  amount           // Transfer amount
}
// Result: recipient receives funds with no link to sender

Client SDK Architecture

Two SDKs for different privacy levels. SpecterClient for stealth addresses, ShieldedClient for ZK proofs. Both run client-side for maximum privacy.

Key Features

  • TypeScript/JavaScript SDK with full type definitions
  • WASM-compiled circuits for browser compatibility
  • Web Worker isolation for proof generation
  • Automatic note management and encryption
  • Streaming payments with SPL token support

Code Example

// === P-01 SDK - Stealth Addresses ===
import { P01Client } from '@p01/sdk';

const client = new P01Client({ cluster: 'devnet' });
const wallet = await P01Client.createWallet();
await client.connect(wallet);

// Send private transfer (stealth address)
await client.sendPrivate(recipientStealthAddress, 1.5);

// Create payment stream
await client.createStream(recipient, 10, 30); // 10 SOL over 30 days

// === P-01 SDK - ZK Shielded Pool ===
import { ShieldedClient } from '@p01/sdk/zk';

const zkClient = new ShieldedClient({ connection, wallet });
await zkClient.initialize(seedPhrase);

// Shield tokens (deposit to private pool)
await zkClient.shield(1_000_000_000n); // 1 SOL

// Private ZK transfer
const zkAddress = ShieldedClient.decodeZkAddress("zk:...");
await zkClient.transfer(zkAddress, 500_000_000n);

// Unshield (withdraw to public)
await zkClient.unshield(publicKey, 500_000_000n);

Security Model

Threat Model

  • Blockchain observers cannot link senders and recipients
  • Transaction amounts are hidden in shielded transfers
  • Spending patterns cannot be analyzed
  • Balance tracking is impossible for third parties

Guarantees

  • Sound: Invalid proofs cannot be generated
  • Complete: Valid spends always produce valid proofs
  • Zero-knowledge: Proofs reveal nothing beyond validity
  • No double-spending: Nullifiers are unique per note

© 2026 PROTOCOL 01 | Built from scratch for privacy