ZK on Solana in 2026: what can you actually use?

What Solana verifies in Aspis, Confidential Balances, Light, Rings, Noir and zkVMs, with compute figures and trust assumptions compared.

I built Aspis, so I have an obvious interest in this comparison. The figures for the other projects come from their own documentation, repositories or published transactions. Where a compute figure covers only the verifier rather than a complete transaction, I say so.

A private-pool withdrawal has to do rather more than check a proof. The program must establish that the spender owns a note in the pool, make sure that note has not been spent before, update the pool and release the tokens. Aspis does all four in one Solana transaction. The program checks an M31 Circle STARK itself, writes the nullifier which prevents a second spend, advances the pool state and transfers the SPL tokens. There is no Groth16 wrapper and no trusted setup.

Solana permits a transaction to request at most 1.4 million compute units; if the program exhausts that budget, the transaction fails and its account changes do not take effect. The largest complete test of the latest Aspis program uses 1,201,757 CU. The preceding construction carried out the corresponding private spend in a finalised mainnet transaction at 1,334,452 CU. The latest figure was measured in the local Solana runtime and that program has not yet been put on a public cluster; the earlier transaction has already shown that direct transparent verification and the private-spend state change fit on mainnet.

The phrase “ZK on Solana” covers several unrelated pieces of work. It may mean hiding the amount of a Token-2022 transfer, proving that compressed account data belongs to a Merkle tree, checking the result of an ordinary Rust program or settling a private payment. These are not versions of one product, and the comparison is useful only if those different jobs remain in view.

The proof Solana actually checks

A proof system has a prover and a verifier. The prover performs the calculation, using any private inputs, and produces a proof. The verifier checks it. There is no logical rule which says that the prover must be a separate machine, but producing these proofs inside a Solana transaction would be impractical and would expose the private inputs. Every system discussed here therefore produces the proof away from Solana and runs only the verifier in the Solana program.

Groth16 needs a proving key and a verification key for the particular circuit being proved. Those keys are made from secret random values which must then be destroyed. If somebody retains enough of that secret, they can manufacture a proof for a false statement. A multi-party ceremony reduces the risk by allowing several people to contribute randomness, since the result is safe if even one of them destroys their contribution, but the ceremony is still a trusted setup.

“Transparent” is the usual cryptographic term for a system which does not need that secret setup; STARKs are normally transparent. This has nothing to do with whether the inputs are private. A transparent proof may reveal its witness, and a Groth16 proof may hide one. The word tells us how the proof system was set up, not what the application publishes.

A STARK can also be wrapped in Groth16. The first prover establishes that the program ran correctly, then a second circuit checks that STARK proof and produces a small Groth16 proof. If the Groth16 proof is what appears in the Solana transaction, Groth16 is what the Solana program checks; the trusted setup and the correctness of the wrapping circuit are part of the system one is relying upon. This is how RISC Zero and SP1 reach Solana. Rings also ends in Groth16, although its circuit proves the payment rather than wrapping a zkVM receipt. Aspis checks the Circle STARK itself.

There is a good reason for the wrapper. Groth16 proofs are tiny and Solana has fast BN254 elliptic-curve operations for their pairing check, so the verifier usually consumes only a small part of a transaction. A direct STARK verifier has to do the hashes, field arithmetic and polynomial checks itself. Aspis’s 1,201,757 CU is therefore not a disappointing Groth16 number; it is the cost of the whole transparent withdrawal, including the state change and token transfer.

A comparison of ZK projects on Solana

If all I wanted were hidden amounts for a new Token-2022 mint, I would use Confidential Balances. If I wanted cheaper account state, I would use Light. For a fixed custom circuit I would look at Noir, and for an ordinary program I would use a zkVM. The comparison becomes interesting for private payments: Rings offers a cheaper Groth16 route with a broader service around it, while Aspis has Solana verify the transparent proof itself and complete the withdrawal atomically.

Solana ZK and privacy projects compared by purpose, on-chain verifier and current implementation
Route The job it does What Solana checks What works now What to know
Aspis Withdraw privately from an SPL-token note pool The M31 Circle STARK itself, followed by the nullifier, pool update and token settlement A finalised mainnet spend in the preceding construction; the latest complete withdrawal measures 1,201,757 CU locally No wrapper or trusted setup; the measurement covers the verifier, nullifier, pool update and token settlement, and the verifier mathematics is checked in Lean
Confidential Balances Hide Token-2022 balances and transfer amounts Sigma proofs and a Bulletproof; no trusted setup A native mainnet verifier; about 111,000 CU for the current batched range-proof check The mint and participants remain public; the documented flow may use several transactions
Light ZK Compression Store accounts and tokens much more cheaply A Groth16 validity proof A developed operator stack, several independent audits and formally checked circuits Compression gives no privacy; clients need access to an indexer and prover
Helius Rings Private SOL and SPL balances and payments Groth16 Beta on devnet; one transaction and about 220,000 CU for a private transfer Proofs currently come from a prover server; the default ring reveals sender and recipient
Noir with Sunspot Verify one fixed, developer-written circuit Groth16 Three working devnet examples with proofs of 324–388 bytes Each circuit has its own keys and verifier, and the circuit itself must be written and reviewed
Bonsol / RISC Zero Prove an ordinary program in a zkVM A Groth16 proof of a RISC Zero receipt Fewer than 200,000 CU for Bonsol verification; the RISC Zero router has a Veridise audit The job is asynchronous and proving needs separate infrastructure; the wrapper retains a setup
SP1 Prove an ordinary program in a zkVM A Groth16 proof of the SP1 result A public example; its verifier uses about 280,000 CU in program-test The integration describes itself as unaudited; proof and public data must fit the transaction
Halo2/KZG Verify a PLONKish custom circuit directly The Halo2 proof itself A one-transaction verifier has run on devnet KZG still uses setup material; larger examples need several transactions
Mosaic Use one interface for Groth16, KZG-PLONK and, eventually, FRI Groth16 or KZG-PLONK today Working Groth16 and KZG-PLONK paths with extensive tests The production-shaped FRI fixture does not yet verify; no external audit has been commissioned
PQZK Demonstrate a direct STARK with post-quantum cryptography A Winterfell STARK A public devnet demonstration with chunked proof upload The proved computation is deliberately small; the project is an unaudited research prototype

Aspis: direct Circle STARK verification inside a payment

Aspis keeps commitments to private notes in a pool. To withdraw, the spender proves knowledge of the secret key for a note in that pool and proves that the payment conserves value, without disclosing the note, its position or the key. The proof also produces a nullifier, which is a serial number tied to that note but does not reveal it. The program rejects a nullifier it has seen before, so a valid note can be spent once and only once.

The latest verifier works over M31, the field of integers modulo 2³¹ − 1, and checks a Circle STARK. The proof bytes are too large for a Solana transaction, so they are put in a Solana account beforehand; this upload approves nothing. The 997-byte withdrawal transaction reads that proof, verifies it, records the nullifier, advances one of eight pool lanes and transfers SPL tokens from the vault. All of that costs 1,201,757 CU. If the proof fails, none of the state changes happen. The preceding construction’s finalised mainnet transaction provides the public-cluster evidence.

Rings uses about 220,000 CU for a private transfer and has a broader service around it. Its Solana program checks Groth16, and the current service supplies the proof. The lower figure follows from that small pairing check; a direct Circle STARK verifier has to carry out the hashes, field arithmetic and polynomial checks inside the transaction. This is an architectural trade, not a like-for-like race.

Aspis formal verification: why Lean matters

Mathematicians prove a theorem by beginning with a statement and taking individual logical steps until they reach the conclusion. Each step has to follow from the ones before it. Unfortunately, people sometimes accept a step which looks right but is not. The familiar false proofs that end with 1 = 0 usually divide by a quantity which has quietly become zero; the surrounding algebra is ordinary enough that the bad step is easy to miss.

Lean is a program which checks the same chain of reasoning in a formal language. It cannot be persuaded by a plausible-looking step: if an argument divides by a − b, Lean will demand a proof that a − b is not zero, and without one the proof stops. Every mathematical result used by the Aspis proof system and verifier has been put through this process for the actual fields, domains and numerical bounds used by the program.

Earlier Aspis versions relied on difficult theorems from published papers. The Lean work removed that dependence by proving the required results directly, and in doing so found a genuine error in the published Reed–Solomon curve-decoding argument. The first coefficient in a perfectly admissible example has weight 4, while the published claim gives an upper bound of 1. The corrected proof repairs the argument in two ways and shows that the numerical bounds used by Aspis are still valid.

The program is written in Rust, not Lean, so the code has to be connected to the mathematics as well. A program called Charon takes selected functions from the actual Rust code, using the compiler’s account of their types, branches and operations. Aeneas turns that extraction into Lean definitions. Lean can then prove that the translated verifier parses the proof, constructs the transcript and reaches the same result as the mathematical verifier. For the mainnet construction, the capstone theorem begins with a successful translated call and derives the complete set of facts needed for acceptance from that one execution. The formal-verification record gives the precise scope and theorem links.

Tests show that selected inputs work, and a paper explains why a construction ought to be sound. Formalisation adds something different: it checks the stated chain of reasoning for the concrete fields, domains and bounds used here. That is how the error in the Hensel estimate was found. It complements the ordinary work of peer scrutiny, tests and deployment rather than replacing it.

Confidential Balances: hidden Token-2022 amounts

Confidential Balances is a Token-2022 extension. A token account holds an encrypted balance and a transfer can keep its amount hidden, so the validator can no longer check the payment by reading two public numbers. The sender supplies an equality proof, a ciphertext-validity proof and a range proof which together show that the encrypted arithmetic is valid and that the resulting values lie in the permitted range.

The first two are short algebraic arguments called sigma proofs; the range proof is a Bulletproof. They need no trusted setup. The Foundation’s current examples put the batched range-proof verifier at about 111,000 CU on Agave 4.0, although that is the range-proof check rather than the whole transfer. The verifier is a native mainnet program and, for the problem it was designed to solve, this is the obvious place to start.

The mint, token accounts, owners and their participation in the transaction remain public; an issuer may also appoint an auditor who can decrypt transfer amounts. This is confidential accounting rather than an anonymous pool. The documented transfer flow may use proof-context accounts and several transactions, so wallets have rather more work to do than they do for an ordinary SPL transfer.

For payroll or confidential balances in a new Token-2022 mint, I would use it. It hides the amounts without asking an application to build a pool, a note tree or a nullifier set. It does not hide the mint, the accounts or the parties to the transaction.

Light ZK Compression: cheaper Solana state

Light Protocol’s ZK Compression deals with the cost of state. Instead of keeping every account as a separate active Solana account, it places compressed accounts in a Merkle tree and records the tree root on chain. That root is a compact commitment to the whole collection. When an account is created or changed, a Groth16 validity proof shows that the supplied data and the proposed update agree with an accepted root.

This can reduce cost by orders of magnitude: Light’s own PDA example compares about 1.6 million lamports for a conventional 100-byte PDA with roughly 15,000 lamports for the compressed version. The older proof format occupies 128 bytes, while the newer prove-by-index route can make the instruction reference smaller still. None of this encrypts the account data; a compressed public token remains public.

An application needs more than a Solana RPC. It needs an indexer to reconstruct accounts from the tree, a prover to produce validity proofs and foresters to maintain the queues and tree updates. Light publishes the operator software and interfaces, so these services may be run independently or bought from a provider such as Helius. The proof prevents a dishonest service from inventing an account, although a broken indexer can still prevent a user from finding one.

Light’s security page lists work by Certora, OtterSec, Accretion, HashCloak, Neodyme and Zellic, formal circuit verification and the record of its trusted setup. That is a substantial production record. Groth16 is a sensible choice for Light because it buys a small and cheap validity proof; the point of the system is cheaper state, not transparent private payments.

Helius Rings: private payments with Groth16 on chain

Helius Privacy, or Solana Rings, represents a private balance as a collection of UTXOs. Each UTXO is a record which may be spent once; a proof consumes the old records and creates new ones without revealing all their contents. This design supports SOL and SPL assets, private balances and transfers between private wallets, rather than being tied to a new Token-2022 mint.

The permissionless default ring hides the asset and amount but leaves the sender and recipient visible. A custom confidential ring can add auditors, allowlists or transfer limits, while a custom anonymous ring uses a relayer to hide the parties as well. The Rings documentation explains these versions clearly, and an application designer needs to decide which of them is actually required.

A private transfer settles in one Solana transaction and consumes about 220,000 CU, including the transfer rather than merely an isolated verifier primitive. A shared tree can presently carry about 54 transfers per block, roughly 130 per second at the block time used by Helius, because every transfer writes to the same account; adding trees raises the total. This is ample for many applications, but the writable tree account, rather than Solana’s advertised transaction rate, sets the capacity of each pool.

Proofs currently come from a prover server, with local proving planned. Confidential rings can decrypt balances locally, but delegated decryption gives the provider a viewing key; anonymous rings currently use delegated decryption. The encrypted index may be served by Helius or another operator. In practical terms, a team choosing Rings must decide who holds the viewing capability and who produces the proof.

The public program checks Groth16, so the wrapping circuit and setup ceremony remain part of the trust placed in the system. In return, Rings uses about one sixth of the transaction limit and already offers deposits, transfers and withdrawals on devnet. It is the main practical competitor to Aspis, but it has made the opposite design choice: cheap Groth16 verification and a proving service instead of direct transparent verification.

Noir and Sunspot: one fixed Solana circuit

Noir is a language for writing arithmetic circuits. The Solana Foundation examples use Sunspot to turn such a circuit into a Groth16 prover and a Solana verifier; the repository includes deployed devnet examples for a simple assertion, an ECDSA signature and a sparse-Merkle-tree exclusion proof, with proofs between 324 and 388 bytes.

This is a good route for a small, stable statement which is naturally expressed as arithmetic. The verifier holds the key for that circuit and avoids carrying a virtual machine through the proof, so a well-designed custom circuit can be both cheaper and easier to inspect than a zkVM program.

The developer must write and review the circuit, generate its keys, rely on the setup ceremony and deploy its verifier; a substantial circuit change repeats much of that work. I would choose Noir over a zkVM for a fixed signature, membership or policy check, but not for a large program which will change every fortnight.

RISC Zero, Bonsol and SP1: zkVMs on Solana

A zkVM proves an ordinary program, saving the developer from turning a large calculation into a bespoke circuit. RISC Zero and SP1 first prove the program’s execution with STARK-based machinery, then wrap that result in Groth16 for Solana. The developer gains programmability and the transaction gains a small proof, but Solana checks the wrapper rather than the STARK.

RISC Zero and Bonsol

The RISC Zero Solana verifier router accepts a wrapped receipt and checks its Groth16 proof. Veridise has reviewed it. This suits a team which already knows how it will produce proofs and wants a common on-chain verifier.

Bonsol adds a market for obtaining the proof. A program requests an execution on chain, a prover node claims it, and the verified result later returns through a callback; a claim expires if the prover stalls. The Groth16 verification costs fewer than 200,000 CU. For a complicated calculation, compiling ordinary Rust for the RISC Zero guest is much easier than writing and maintaining a large Noir circuit.

The request and callback occur in different transactions, so the application must cope with proof latency and with a request which expires unproved. A distributed prover also needs the program image and the inputs it is meant to use. This is perfectly sensible for asynchronous computation, but it cannot be treated as one atomic on-chain calculation.

SP1

The SP1 Solana integration follows the same route: SP1 proves the program and Groth16 reaches Solana. Its example verifier uses about 280,000 CU. The proof is 260 bytes, in addition to the public values, which count towards Solana’s 1,232-byte transaction-data limit.

A team already committed to SP1 may prefer its development environment; the Solana repository currently describes the integration as unaudited. RISC Zero has the reviewed router, while Bonsol has the more complete job protocol. All three are good answers to “how do I prove this program?” and none is attempting to be a direct transparent private-payment verifier.

Direct proof verification: Halo2, Mosaic and PQZK

A direct verifier checks the native proof rather than a Groth16 proof saying that another verifier accepted it. Solana must consequently perform the underlying hashes and field arithmetic itself. Halo2, Mosaic and PQZK show three different stages of this work, with different answers to setup, transaction shape and application scope.

Halo2/KZG

The Solana-Plonk Halo2 verifier checks a Halo2 proof directly. A shuffle example has run on devnet in one transaction, with a current local figure of 1,123,442 CU; larger examples use three transactions and store intermediate verifier state in accounts. This is useful for a team already working with PLONKish circuits and avoids a Groth16 wrapper.

This Halo2 implementation uses KZG polynomial commitments, which require structured setup material. It is direct, but it is not transparent. For the larger examples, the application must also authenticate, resume and eventually clean up the intermediate verifier state left between transactions.

Mosaic

Mosaic provides one Solana interface for several proof systems. It reports roughly 84,000 CU for one Groth16 verification, about 260,000 CU for a batch of five and 973,388 CU for KZG-PLONK, with a substantial collection of unit, integration and property tests. That common interface is useful to a team which expects to change proof systems.

The transparent FRI route is not there yet. Mosaic’s compute record estimates roughly 7.8 million CU for the intended chunked version; a minimal depth-zero fixture passes, while the production-shaped fixture ends in VerificationFailed. The working product today is Groth16 and KZG-PLONK, not a Solana STARK verifier.

PQZK

PQZK verifies a Winterfell STARK on devnet and combines it with SLH-DSA signatures and an ML-KEM encrypted message. The proof is uploaded into an account in chunks. Across 100 recorded runs, STARK verification averaged 1,104,510 CU, while signature finalisation was a separate instruction averaging about 501,000 CU.

PQZK has put a hash-based transparent verifier on a public Solana cluster, which is a worthwhile engineering result. Its proved execution is a small affine-counter trace, and the repository does not claim a complete authenticity proof for the whole message workflow. It establishes the verifier rather than a substantial application state change.

Private Channels, Arcium and other models

Solana Private Channels keep execution inside an institution-controlled perimeter and use mainnet to move value into and out of it. A bank may want exactly that arrangement, but Solana validators are not checking each private calculation; the channel operator controls participation, ordering and visibility.

Arcium uses multi-party computation, in which several nodes calculate with encrypted data without any one node seeing all the inputs. That is useful for auctions, games and calculations which are not naturally expressed as one proof, but the security rests on the MPC cluster rather than on a proof verifier inside the Solana transaction.

Elusiv is historical rather than current. It once offered private transfers and swaps on Solana mainnet, but the team closed the protocol in February 2024 and disabled deposits and swaps.

Which Solana ZK system fits which job?

For a transparent private pool whose proof must be checked directly by Solana, the relevant questions are whether the payment settles atomically and whether the native proof, rather than a wrapper, reaches the program. Aspis’s measured path answers both: the proof authorises the spend, the nullifier prevents replay, the pool changes and the SPL tokens move before the transaction commits. The preceding construction has a finalised mainnet record; the latest complete Circle-STARK withdrawal fits in 1,201,757 CU locally.

There would be no sense using Aspis to compress public account state or to prove an arbitrary Rust program. Confidential Balances is the sensible native option for hidden amounts in a new Token-2022 mint, Light is the mature option for cheaper state, Noir suits a fixed circuit, and I would use RISC Zero or Bonsol for a sizeable program whose answer may arrive asynchronously.

Rings is the closest private-payment alternative. It has the lower CU figure and a wider product surface, but its Solana program accepts Groth16 and its current proving model uses a service. That is the better route when the setup and wrapper are acceptable; a direct transparent check is a different requirement.

What the comparison shows

Groth16 will remain popular on Solana because it is cheap, and it is a sensible engineering choice when a setup ceremony and wrapper are acceptable, particularly for zkVMs and fixed circuits. Confidential Balances and Light are better still when their narrower jobs are the ones that need doing.

The conclusion is narrower than “ZK on Solana” as a whole. For a transparent private payment whose native proof is checked by Solana and whose state transition settles atomically, Aspis is the strongest current entry in this comparison. Its program verifies a Circle STARK, prevents the double spend, changes the pool and transfers the tokens in one transaction.

Dominic Barker teaches mathematics and built Aspis. His work covers coding theory, formal proof and cryptographic software. The source code, Lean proofs and archived mainnet material are available through the Aspis repository.