> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cloak.ag/llms.txt
> Use this file to discover all available pages before exploring further.

# Protocol Architecture

> Current end-to-end data flow across app, SDK, and shield-pool runtime

Cloak is a UTXO privacy system on Solana with four active runtime surfaces:

* Your app's wallet UX, encrypted local cache, and scan/export flows
* SDK proof generation, transaction coordination, and chain-note scan/decrypt
* Shield Pool on-chain proof verifier + state machine
* Circuit layer constraints (2-in/2-out transaction circuit)

## End-to-end flow

<img src="https://mintcdn.com/cloak/GTE3T6O9bn8kiOl3/architecture/diagrams/system-architecture.svg?fit=max&auto=format&n=GTE3T6O9bn8kiOl3&q=85&s=ef6b29f7551dd52b5a22f371baa9aa83" alt="Cloak end-to-end runtime architecture" style={{ width: "100%", borderRadius: 12, border: "1px solid var(--mint-border)" }} width="1280" height="740" data-path="architecture/diagrams/system-architecture.svg" />

## Core transaction model

* The canonical path is UTXO `transact` / `transact_swap` (2 inputs, 2 outputs, tree height 32).
* Public inputs are `264` bytes: `root[32] + publicAmount[8] + extDataHash[32] + mint[32] + nullifiers[64] + commitments[64] + chainNoteHash[32]`.
* `publicAmount` meaning:
  * `> 0`: deposit into pool
  * `< 0`: withdrawal from pool
  * `= 0`: shield-to-shield transfer
* The same proof/public-input shape is consumed by the on-chain program.

## Fee model (gross, fee, net)

* Fees apply only to withdrawals and swaps (`publicAmount < 0`); deposits and shield-to-shield
  transfers are fee-free
* SOL pool fee: `5_000_000` lamports fixed + `gross * 3 / 1000` variable
* SPL pool fee (USDC/USDT): `gross * 3 / 1000` variable only, in the withdrawn token
* Net recipient amount: `gross - fee`
* Minimum deposit: `10_000_000` lamports (SOL pool only)

See [Fee Model](/protocol/fee-model) for worked examples and the per-flow breakdown.

## On-chain state

Shield Pool maintains:

* Merkle tree (`MERKLE_TREE_HEIGHT = 32`)
* Root history ring (`ROOT_HISTORY_SIZE = 100`)
* Nullifier PDAs (`["nullifier", pool_pubkey, nullifier_hash]`) for spent checks
* Mint-scoped Pool/Treasury PDAs (`["pool", mint]`, `["treasury", mint]`)
* SwapState PDA (`["swap_state", pool_pubkey, nullifier]`) for two-phase swaps

## Viewing keys and history scanning

* Viewing-key registration is enforced by default for SDK transaction paths.
* User signs a fixed sign-in message; the SDK submits the registration and binds the 32-byte viewing key to the wallet identity.
* Scanner path is chain-native: SDK reads program transactions from RPC, decrypts compact chain notes with `nk`, verifies `chainNoteHash` integrity, and computes running balance/fees.
* History UIs commonly use encrypted local cache and support explicit `Clear cache & rescan`.

## Program IDs

Current deployment program ID:

* `zh1eLd6rSphLejbFfJEneUwzHRfMKxgzrgkfwA6qRkW` (default)

If your app targets a deployment with a different address, pass that `programId` explicitly to your SDK client.
