ZK on Solana today
The syscalls, groth16-solana, ZK Compression, confidential transfers after their 2026 return, and what bigger v1 transactions change.
- Syscalls: alt_bn128 group operations and compression (live since July 2024), little-endian variants and G2 operations (June 2026), BLS12-381 (June 2026), and Poseidon.
- groth16-solana verifies a proof for about 78–109k CU, depending on the number of public inputs. Its 0.0.1 release was audited; newer ones say as-is.
- ZK Compression is live on mainnet. Its 128-byte proofs cover inclusion of up to eight compressed accounts.
- Confidential transfers were disabled in June 2025 after a Fiat–Shamir bug and re-enabled on 2026-06-04.
- v1 transactions of up to 4,096 bytes are live since 2026-09-15. They have room for bigger proofs, but no address lookup tables.
The syscalls
| Syscall / feature | What it does | Mainnet |
|---|---|---|
sol_alt_bn128_group_op | BN254 G1 add, multiply, pairing check | 2024-07-04 |
sol_alt_bn128_compression | Compress / decompress G1 and G2 points | 2024-07-11 |
| SIMD-0284 | Little-endian variants | 2026-06-08 |
| SIMD-0302 | G2 addition (535 CU) and multiplication (15,670 CU) | 2026-06-10 |
| SIMD-0388 | BLS12-381 operations | 2026-06-12 |
sol_poseidon | Poseidon over BN254 (x⁵, circom parameters), 61·n² + 542 CU | live; 32-byte inputs enforced 2026-03-13 |
Verifying Groth16 in a program
groth16-solana from Light Protocol is the usual verifier. It takes the proof as proof_a (64 bytes, negated), proof_b (128) and proof_c (64), with public inputs as 32-byte big-endian values, and runs a single four-pair pairing check. Its benchmarks:
| Public inputs | Compute units |
|---|---|
| 1 | 78,293 |
| 2 | 82,704 |
| 4 | 91,448 |
| 8 | 108,762 |
The crate's 0.0.1 release was audited as part of Light Protocol's v3 audit. The current README offers it as-is. The lab encodes its proofs in this exact layout and checks them with an independent pairing library, so you can see the bytes a program would receive.
ZK Compression
Light Protocol's programs are live on mainnet (Light System Program SySTEM1eSU2p4BGQfQpimFEWWSC1XDFeun3Nqzz3rT7, Account Compression compr6CUsB5m2jS4Y3831ztGSTnDpnKJTKS95d64XVq). Compressed accounts are leaves in Poseidon state trees of height 26, and a 128-byte Groth16 validity proof covers one to eight of them. The programs were audited by OtterSec, Neodyme and Zellic, and Reilabs formally verified the circuits. Newer v2 trees can skip the proof entirely when an account is proven by index.
Confidential transfers, after the break
- 2025-06-10: zkSecurity reports a missing component in a Fiat–Shamir transcript of the ZK ElGamal Proof program. It allowed forged proofs.
- 2025-06-11 to 06-19: Token-2022 disables confidential transfers, then the proof program is disabled at epoch 805. No exploit is known.
- 2026-06-04: the proof program is re-enabled (epoch 982). Token-2022 is redeployed on 2026-06-17 after audits by Code4rena, Least Authority, zkSecurity, Trail of Bits and QEDIT.
- 2026-09: in the current SDK, both confidential keys derive from one HKDF-SHA512 chain over a wallet signature of
solana-conf-bal/v1.
Under the hood: twisted ElGamal on ristretto255, 64-byte ciphertexts, and amounts split into a 16-bit low part and a 32-bit high part so each piece can be decrypted with a discrete-log search. The available balance is also kept under AES so the owner can read it quickly.
Bigger transactions
The v1 transaction format (SIMD-0385, carrying SIMD-0296's larger size) went live on 2026-09-15. A v1 transaction can be up to 4,096 bytes with up to 64 accounts listed inline. It has no address lookup tables, and anything over 1,232 bytes has to be sent base64-encoded. Legacy and v0 transactions keep the old limit.
For proofs, that's room for a Groth16 proof with dozens of public inputs, or a meaningful slice of a hash-based proof. A full 99.6 KB STARK is still 24.3× too big for one transaction, but uploading it to an account now takes about 26 transactions instead of 97.
A checklist for builders
- Check who made phase 2 of your circuit's setup, and publish the transcript.
- Bind recipients and any other context into public inputs.
- Put every message, key and commitment into your Fiat–Shamir transcripts.
- Store nullifiers in their own accounts so a repeat claim fails on account creation.
- Keep the verifying key behind an upgrade path you can explain to users.
- Write down what happens to your users' data on Q-day: secrecy and soundness, separately.
Sources
- Agave syscalls agave syscalls/src/lib.rsRegistration of sol_alt_bn128_group_op, sol_alt_bn128_compression, sol_poseidon.
- Agave cost table agave program-runtime/src/execution_budget.rsCompute-unit prices for alt_bn128, compression and Poseidon syscalls.
- solana-poseidon solana_poseidon crate sourceBn254X5 parameters, circom-compatible, up to 12 inputs.
- groth16-solana Lightprotocol/groth16-solanaByte layout (A negated, big-endian) and measured compute units.
- ZK Compression docs Merkle trees and validity proofs128-byte proofs of state-tree inclusion and address non-inclusion.
- Solana post-mortem ZK ElGamal Proof program bug, June 2025A missing transcript component let proofs be forged; confidential transfers were disabled.
- Token-2022 #657 Confidential transfer re-enablement tracking issueAudits and the 2026 re-enable; closed as completed 2026-09-03.
- zk-sdk encryption solana-program/zk-elgamal-proof · zk-sdk/src/encryptionTwisted ElGamal: H, P = s⁻¹H, C = xG + rH, D = rP, baby-step giant-step decryption.
- Larger transactions solana.com: larger transaction sizesv1 transactions up to 4,096 bytes, active on mainnet since 2026-09-15.
- SIMD-0296 Larger transactions proposalThe 4,096-byte limit, carried by the v1 format (SIMD-0385).
checked 2026-10-16 against the documents above
Outside this chapter
- Writing and deploying a verifier program
- Bulletproofs-style range proofs used inside confidential transfers
- Off-chain ZK coprocessors and their trust models