Privacy has always been an interesting problem on public blockchains because transparency is one of the things that makes them useful in the first place.
On Stacks, transaction history, balances, and addresses are publicly observable. That is valuable for verification, but there are applications where exposing the complete financial relationship between addresses is not desirable.
That question is what led to Stacks Shield.
Stacks Shield is an open-source privacy protocol for Stacks that uses zkSNARKs to allow users to move STX and SIP-10 assets through shielded notes while keeping the underlying note ownership and amounts private.
What started as an exploration of private STX transactions has now grown into a multi-asset privacy system supporting STX, sBTC, and USDCx on Stacks Testnet, with a published developer SDK.
This post introduces what we built, why we built it, how the system works, and where we want to take it next.
From private STX to a multi-asset privacy layer
The first version of Stacks Shield was designed around native STX.
The basic model is straightforward:
-
A user deposits STX into a privacy pool.
-
The deposit becomes a shielded note represented publicly by a cryptographic commitment.
-
The user’s wallet keeps the information required to spend that note.
-
When the user wants to move the funds, a zkSNARK proves that they are authorized to spend a valid note without revealing the note’s private information.
-
A relayer submits the resulting transaction.
-
The recipient receives a new shielded note.
-
The funds can eventually be withdrawn to a transparent Stacks address.
The public chain can verify that the operation is valid without learning the private details contained inside the note.
That foundation worked well enough to raise the next question:
Could the same privacy infrastructure support assets beyond STX?
That is where SIP-10 support came in.
Adding sBTC and USDCx without fragmenting privacy
The goal was not to create a separate privacy protocol for every token.
We wanted one system that could support multiple assets while preserving the existing STX implementation.
The design therefore treats SIP-10 support as an additive extension to the existing STX privacy core. The native STX protocol remains frozen, while the SIP-10 layer reuses shared components such as the privacy registry and note infrastructure.
Today, the testnet deployment supports:
-
STX
-
sBTC
-
USDCx
And the architecture is designed around registered SIP-10 assets rather than hard-coded token implementations.
The on-chain asset-registry is the source of truth for supported assets. The API exposes that registry through asset discovery, and the SDK uses the resulting metadata to route operations to the appropriate pool and verifier. Adding another registered SIP-10 asset therefore does not require creating another SDK implementation.
This was an important architectural decision.
We wanted:
One privacy system, many assets.
How privacy works
At the heart of Stacks Shield is the concept of a shielded note.
A note contains information such as:
-
amount
-
owner keys
-
blinding value
-
asset information where applicable
The blockchain does not store that information in plaintext as the representation of the user’s private balance.
Instead, the note is represented publicly by a cryptographic commitment.
For native STX, the commitment is based on:
Poseidon4(amount, ownerPkX, ownerPkY, blinding)
For SIP-10 assets, the asset itself becomes part of the cryptographic commitment:
Poseidon2(
Poseidon4(amount, ownerPkX, ownerPkY, blinding),
asset_id
)
where asset_id is derived from the token contract principal.
This matters because sBTC and USDCx can share the same underlying commitment infrastructure without becoming interchangeable.
A USDCx note cannot simply be treated as an sBTC note because the asset is cryptographically bound to the commitment.
One shared Merkle tree
Another deliberate design choice was to avoid creating a separate anonymity infrastructure for every asset.
All commitments are stored in a shared commitment tree.
That means STX, sBTC and USDCx notes can participate in the same underlying commitment infrastructure while their asset identities remain cryptographically bound.
The privacy model also uses nullifiers.
When a note is spent, its nullifier is published. The registry can therefore reject a second attempt to spend the same note without revealing which note was spent.
This gives us the basic privacy primitives required for the shielded lifecycle:
commitments → Merkle membership → zkSNARK proofs → nullifiers → new commitments
What actually happens during a private transaction?
Consider Alice and Bob.
Alice has sBTC in a transparent wallet.
She shields it through STX Shield.
Her wallet generates the note information and creates the corresponding commitment. The proof is generated client-side using the proving engine. The encrypted note information can be published as opaque ciphertext, while the information needed to interpret the note remains with the user’s wallet.
Alice can then:
Shield → Transfer → Split → Merge → Withdraw
For a private transfer to Bob, Alice’s wallet generates a proof demonstrating that:
-
the input note exists,
-
she can spend it,
-
the Merkle path is valid,
-
the nullifier is valid,
-
the resulting commitments satisfy the circuit’s rules,
-
and, for SIP-10, the asset remains the same.
The proof does not reveal the private note information.
The transaction is then submitted through the relayer rather than directly from Alice’s wallet. The relayer constructs and broadcasts the on-chain transaction, meaning the Stacks transaction does not identify Alice as the sender of the private operation.
Bob receives a new shielded note.
Later, Bob can withdraw the asset to a different transparent address.
The resulting public transaction shows the withdrawal, but the privacy protocol does not provide a public link back to the original shielded note.
Where zkSNARKs and zkVerify fit
The proof system is built around Noir and UltraHonk circuits.
There are circuits for:
-
shield
-
transfer
-
split
-
merge
-
withdraw
with native STX and SIP-10 variants. SIP-10 circuits additionally bind the asset_id into the public inputs and commitments.
Proofs are generated client-side through @aztec/bb.js.
The next challenge is verification.
UltraHonk proofs are currently too expensive to verify directly inside Clarity, and Clarity does not currently provide the elliptic-curve pairing primitives required for this style of direct SNARK verification.
Stacks Shield therefore uses zkVerify as the current verification and aggregation layer.
The flow is:
Private witness
↓
zkSNARK circuit
↓
Proof generated
↓
zkVerify
↓
Proof verification + aggregation
↓
Aggregation root
↓
Stacks
↓
On-chain membership verification
zkVerify verifies proofs and aggregates them into an aggregation root. The relayer publishes that root on Stacks. The Stacks contracts then only need to verify that the relevant public-input leaf belongs to a valid aggregation root, rather than executing the full SNARK verification themselves.
This is an important part of the current architecture, and also one of the areas we want to keep improving.
The API and Relayer
The privacy protocol is not just a collection of Clarity contracts.
There is a complete backend layer supporting the SDK.
The API acts as the canonical source for protocol metadata and indexed chain information.
It indexes:
-
commitments
-
encrypted notes
-
aggregation roots
-
protocol statistics
-
registered assets
-
relevant contract events
Importantly, the API does not store note amounts, note secrets, or mappings between nullifiers and commitments. The note feed contains opaque encrypted data and public locators.
The relayer handles the execution side.
It validates proof metadata, submits proofs for verification, tracks aggregation, publishes aggregation roots, and constructs the eventual Stacks transaction.
This separation lets the SDK remain relatively simple for developers.
The SDK
The next step after getting the protocol working was making it usable.
We did not want developers integrating with:
-
Clarity contracts
-
Merkle trees
-
proof generation
-
zkVerify
-
nullifiers
-
asset registries
-
relayer APIs
individually.
The SDK is intended to be the integration surface.
The published package is:
npm install @stacks-shield/sdk
A developer can work with the protocol through a unified interface while the SDK handles the underlying routing.
For example:
const shield = new STXShield({
network: "testnet",
signer,
proofEngine,
noteVault,
});
await shield.shield(100, "USDCx");
The SDK contains injectable interfaces for the proving engine, wallet signer, API provider, relayer provider, zkVerify integration and local note storage.
The objective is simple: privacy should be something an application can integrate rather than rebuild.
Testnet: the part we cared about most
A privacy protocol can look convincing in a diagram and still fail when real components are connected.
We wanted to get past that point.
Stacks Shield is currently running on Stacks Testnet, and the multi-asset implementation has been exercised against the real testnet sBTC and USDCx contracts rather than local mock tokens.
We validated the complete lifecycle for:
STX
Shield
↓
Scan
↓
Transfer
↓
Split
↓
Merge
↓
Withdraw
USDCx
The same complete private lifecycle was exercised using the real SIP-10 token.
sBTC
The same lifecycle was exercised with real testnet sBTC, including a larger-value test and withdrawal to a new transparent address.
Across the three assets, the SDK-level validation covered:
-
shielding
-
note discovery
-
private transfers
-
splitting
-
merging
-
withdrawals
-
replay rejection
-
value conservation
-
asset-aware routing
The project documentation records the reusable all-asset SDK test suite for STX, USDCx and sBTC.
This is the milestone that matters most to us: the architecture isn’t only deployed; the full path has been exercised end-to-end.
What happens to the original STX implementation?
Nothing.
That was one of our strict design requirements.
The native STX protocol was deployed as a frozen core.
SIP-10 support was introduced as an additive extension rather than modifying the existing STX contracts. This means the original STX behaviour remains intact while the new SIP-10 layer introduces multi-asset privacy capabilities.
That gives the system two important properties:
Backward compatibility
Existing STX notes and flows continue to work.
Extensibility
Future SIP-10 assets can use the same privacy infrastructure through registration rather than requiring another protocol implementation.
What we learned building it
One of the most useful lessons from building STX Shield has been that the hard part isn’t a single cryptographic primitive.
It is making all of the pieces agree.
The system crosses several boundaries:
Wallet
↓
SDK
↓
Proof Engine
↓
API / Relayer
↓
zkVerify
↓
Aggregation
↓
Clarity
↓
Stacks
A failure in indexing can make a perfectly valid note appear missing.
A stale Merkle tree can make a valid proof unusable.
An incorrectly routed verifier can make a valid SIP-10 proof fail.
A missing asset binding can undermine isolation between tokens.
A relayer error can break an otherwise correct proof flow.
Live testnet validation exposed several of these integration problems and forced us to test the protocol as a system rather than as isolated components.
That has probably been one of the most valuable parts of the project.
Privacy needs an anonymity set
There is also a broader question that we think deserves more attention on Stacks:
How useful is a shielded pool if very few people use it?
Zero-knowledge proofs can hide the relationship between a note and a transaction, but privacy is not created by mathematics alone.
The size and activity of the anonymity set matter.
A pool with many users, many notes and frequent transactions gives observers a much harder correlation problem than a pool with only a handful of participants.
That is why STX Shield is being designed as reusable infrastructure rather than a privacy feature tied to one application.
The long-term goal is to make shielded infrastructure available to more wallets, applications, payment flows and DeFi protocols across Stacks.
More legitimate activity in the same privacy infrastructure means a stronger anonymity set.
Where we go from here
The current testnet milestone is not the finish line.
There are several areas we want to continue working on.
Security
The protocol needs serious external security review before any mainnet deployment.
That includes the Clarity contracts, circuits, SDK, relayer and surrounding infrastructure.
More integrations
Privacy becomes considerably more useful when applications can integrate it directly.
The SDK is therefore an important part of the next stage.
More assets
The SIP-10 architecture was intentionally designed around registry-driven asset support.
The goal is to make adding another compatible asset primarily an on-chain registration process rather than another round of protocol development.
Decentralizing execution
The relayer currently provides an important part of the transaction flow.
Longer term, we want to investigate ways to make execution more decentralized while preserving the privacy properties of the system.
Reducing external verification dependencies
Today, zkVerify is an important part of the architecture.
That is useful for getting a working system running, but we don’t consider an external verification layer the final destination.
One direction we are interested in is self-hosted proof verification and aggregation.
The longer-term question is even more interesting:
What would it take for Stacks to verify ZK proofs natively?
That could involve changes such as pairing-friendly cryptographic primitives or other Clarity-compatible verification mechanisms. The current architecture makes this a concrete engineering and ecosystem question rather than a theoretical one.
Why we are building this
The broader idea behind Stacks Shield is bigger than private transfers.
Stacks is increasingly becoming a place where Bitcoin-backed assets and applications can be used in more sophisticated ways.
As that happens, privacy becomes an important part of the application layer.
Users may want to:
-
move assets without exposing their entire transaction history,
-
receive payments privately,
-
manage treasury operations,
-
interact with DeFi without revealing every position,
-
transfer value between shielded identities,
-
or simply have more control over what their financial activity reveals publicly.
Applications should not have to build a new privacy protocol every time they need one of these capabilities.
That’s the problem we’re trying to address.
STX Shield is now open
STX Shield is now publicly available as an open-source project.
GitHub
Repository:
SDK
npm:
@stacks-shield/sdk
Install it with:
npm install @stacks-shield/sdk
Testnet
Stacks Shield Testnet:
The current implementation supports STX, sBTC and USDCx, with the complete shielded lifecycle available on Stacks Testnet.
Closing
Stacks Shield started with a simple question:
Can we build useful zero-knowledge privacy infrastructure directly around the Stacks ecosystem?
The answer we have today is a working testnet implementation.
It generates zkSNARK proofs client-side, uses zkVerify for verification and aggregation, settles through Clarity contracts, routes multiple assets through a common privacy architecture, and exposes the system through a developer SDK. The testnet implementation has now been exercised across native STX, sBTC and USDCx.
There is still a lot to prove before this should be considered production-ready.
Security reviews, broader adoption, stronger anonymity sets, decentralized infrastructure, and eventually a path toward more native ZK verification on Stacks are all part of the work ahead.
But the foundation is now public.
STX Shield is live on Stacks Testnet, the SDK is published, and the code is open for developers to inspect, test, build with, and challenge.
If you’re building on Stacks and are interested in zero-knowledge, privacy, sBTC, SIP-10, or ZK infrastructure, we’d love to have you take a look.
Links
-
Testnet: https://shield-stx.alkebulant.com/
-
Documentation:Stacks-shield v1.0.0-beta.1 Whitepaper
STX Shield is currently a testnet project. The implementation should be treated accordingly until further security review and mainnet readiness work are completed.





