This guide gives you a high-level introduction to the Light Protocol architecture and is a great starting point for learning the fundamentals.
There are three fundamentals that Light introduces to Solana to enable privacy:
Combined with the Light verifier architecture highlighted below, these fundamentals enable Private Solana Programs.
Let's take a quick look at each of the fundamentals before we dive into how they together enable Private Solana Programs.
Light Protocol allows on-chain state to be encrypted. Only the user can decrypt their private state; hence they essentially "own" it. Private state can be owned by a single user or a set of users sharing a decryption key.
Public elements of your program logic can remain unencrypted.
For example, consider an NFT listing on Solana; its public state (e.g., price) is visible to all, including the fact that it's up for sale. But offers and trades should remain private. So if you make an offer on my NFT, the offer remains private, encrypted to my personal account. If I accept your offer, the details of this transaction are only between us - to the rest of the world, it's merely encrypted bytes on the blockchain.
Two questions emerge from this model:
1. How do we update this private state on-chain without revealing clues about which state belongs to which user?
2. How do we validate state transitions in a manner that lets programs and validators agree to the state transition, even when it is encrypted?
Let's answer them one by one.
Solana's account model inherently leaks information about which state is updated by whom because even if you encrypt the state, you would still see which account was updated at what time. So we need an alternative.
Light Protocol's solution is simple. Instead of mutating account variables in place with each transaction, we encrypt the state in the client, send it on-chain, and append the new encrypted state to a linearly growing list.
With this, we're not updating data in place; we're simply adding to it, concealing which past state was amended with any new transaction. This approach resembles how Bitcoin does it but with an added layer of encryption.
The encrypted state emitted with each new transaction are Unspent Transaction Outputs (UTXOs).
Every Light transaction emits new UTXOs. Each UTXO has a nullifier, signaling it's been spent, and a UTXO hash (commitment), validating the UTXO. The nullifier and commitment are derived from the UTXO in a deterministic way such that on-chain observers cannot tell which UTXO they belong to unless they own the UTXO.
For example, say you want to send 1 USDC through Light Protocol. What you're actually doing is invalidating your preceding UTXO (confirming your ownership of 1 USDC) and emitting a new UTXO, encrypted to the recipient's Light account's public key. This new encrypted UTXO is then appended to the list of all UTXOs on-chain.
Your 1 USDC shifts hands without any on-chain token movement. All that's visible on-chain is the addition of a few encrypted bytes (a UTXO) to a growing list of encrypted UTXOs.
In doing so, Light Protocol essentially adds a UTXO model to Solana, ensuring the details of on-chain operations remain private because state is encrypted and state updates don't happen in place anymore.
One final puzzle to solve: how do we convince Solana validators that these client-computed state transitions are valid? Here is where zk-SNARKs come into play.
The conventional mechanism of constraint enforcement in public Solana programs involves clear-text on-chain computation over custom program logic. "Program logic" is almost always an escrow with some unique constraints.
With Light Protocol, however, the program logic can be encoded into zero-knowledge circuits on the client side. The client then generates the computation and an accurate proof. This proof is then sent on-chain, where a dedicated verifier program, crafted specifically for the circuit, checks its validity.
For example, if you're transferring tokens, the proof of rightful ownership is sent on-chain. A verifier, built by the developer to match the circuit, verifies the zk-proof without having to know the private elements of the zk-proof.
If the verification is successful, the custom verifier Program calls a built-in native system verifier, which runs additional security checks and then calls Light's Merkle tree program, inserting the new UTXOs' commitments and the invalidated UTXOs' nullifiers.
The aforementioned custom verifier program and its dedicated zero-knowledge circuit are what we call Private Solana Program (PSP). Light offers the toolkit (SDK & CLI) to construct the Program and its circuit.
PSPs are permissionless. However, Light has a range of built-in native PSPs which cover the most common use cases (e.g., token transfers), so you don't necessarily have to build a custom PSP for what you want to achieve.
After this introduction to Light, you'll probably want to do one of these two things: